Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 通过网络装载打开时正确关闭文件描述符_C_Remote Access_File Descriptor_Mount Point - Fatal编程技术网

C 通过网络装载打开时正确关闭文件描述符

C 通过网络装载打开时正确关闭文件描述符,c,remote-access,file-descriptor,mount-point,C,Remote Access,File Descriptor,Mount Point,我目前正试图弄清楚,当文件描述符指向远程文件且连接丢失时,如何正确关闭它 void *write_thread(void* arg); int main() { pthread_t thread; int fd = -1; if(-1 == (fd = open("/mnt/testfile.txt", O_CREAT | O_RDWR | O_NONBLOCK, S_IRWXU))) { fprintf(stderr, "Error oppe

我目前正试图弄清楚,当文件描述符指向远程文件且连接丢失时,如何正确关闭它

void *write_thread(void* arg);

int main()
{
    pthread_t thread;
    int fd = -1;

    if(-1 == (fd = open("/mnt/testfile.txt", O_CREAT | O_RDWR | O_NONBLOCK, S_IRWXU)))
    {
        fprintf(stderr, "Error oppening file : %m\n");
        return EXIT_FAILURE;
    }
    else
    {
        if(0 > pthread_create(&thread, NULL, write_thread, &fd))
        {
            fprintf(stderr, "Error launching thread : %m\n");
            return EXIT_FAILURE;
        }
        fprintf(stdout, "Waiting 10 seconds before closing\n");
        sleep(10);
        if(0 > close(fd))
        {
            fprintf(stderr, "Error closing file descriptor: %m\n");
        }
    }
}

void *write_thread(void* arg)
{
    int fd = *(int*)arg;
    int ret;

    while(1)
    {
        fprintf(stdout, "Write to file\n", fd);
        if(0 > ( ret = write(fd, "Test\n", 5)))
        {
            fprintf(stderr, "Error writing to file : %m\n");
            if(errno == EBADF)
            {
                if(-1 == close(fd))
                {
                    fprintf(stderr, "Close failed : %m\n");
                }
                return NULL;
            }
        }
        else if(0 == ret)
        {
            fprintf(stderr, "Nothing happened\n");
        }
        else
        {
            fprintf(stderr, "%d bytes written\n", ret);
        }
        sleep(1);
    }
}
我有一个简单的示例程序,它在sshfs挂载文件夹上打开一个文件描述符并开始写入该文件

我找不到如何处理失去连接的情况

void *write_thread(void* arg);

int main()
{
    pthread_t thread;
    int fd = -1;

    if(-1 == (fd = open("/mnt/testfile.txt", O_CREAT | O_RDWR | O_NONBLOCK, S_IRWXU)))
    {
        fprintf(stderr, "Error oppening file : %m\n");
        return EXIT_FAILURE;
    }
    else
    {
        if(0 > pthread_create(&thread, NULL, write_thread, &fd))
        {
            fprintf(stderr, "Error launching thread : %m\n");
            return EXIT_FAILURE;
        }
        fprintf(stdout, "Waiting 10 seconds before closing\n");
        sleep(10);
        if(0 > close(fd))
        {
            fprintf(stderr, "Error closing file descriptor: %m\n");
        }
    }
}

void *write_thread(void* arg)
{
    int fd = *(int*)arg;
    int ret;

    while(1)
    {
        fprintf(stdout, "Write to file\n", fd);
        if(0 > ( ret = write(fd, "Test\n", 5)))
        {
            fprintf(stderr, "Error writing to file : %m\n");
            if(errno == EBADF)
            {
                if(-1 == close(fd))
                {
                    fprintf(stderr, "Close failed : %m\n");
                }
                return NULL;
            }
        }
        else if(0 == ret)
        {
            fprintf(stderr, "Nothing happened\n");
        }
        else
        {
            fprintf(stderr, "%d bytes written\n", ret);
        }
        sleep(1);
    }
}
当连接断开时,即拔下主板之间的以太网电缆,无论我是否使用O_NONBLOCK标志,主线程中的闭合始终会阻塞

写入调用有时会立即失败并出现EBADF错误,有时会在失败之前持续很长时间

我的问题是,当连接丢失时,写调用并不总是失败,因此我不能将事件触发到线程中,也不能从主线程触发它,因为close永远阻塞

所以我的问题是:如何在C语言中正确处理这种情况

问题是:如何在C语言中正确处理这种情况

你根本不能。文件句柄设计为统一和简单,无论它们指向何处。当一个设备被挂载,与它的物理或虚拟连接崩溃时,即使在命令行级别,事情也变得棘手

问题是:如何在C语言中正确处理这种情况


你根本不能。文件句柄设计为统一和简单,无论它们指向何处。当安装设备时,与设备的物理或虚拟连接崩溃,即使在命令行级别,事情也会变得棘手。

远程文件系统存在一个根本问题,一方面,为了保持可用的性能,您必须缓存东西,另一方面,在多个客户端中缓存可能会导致服务器看不到的冲突

例如,NFS在默认情况下选择缓存,如果缓存是脏的,它只会挂起,直到连接恢复

表明类似的行为

从grepping sshfs'来看,它似乎根本不支持O_非块

这些都与C无关

在我看来,您最好的选择是切换到,并使用例如-o soft-o timeo=15-o retrans=1安装


在某些情况下,当存在网络断开连接时,这可能会导致数据损坏/丢失,主要是当存在多个客户端或客户端崩溃时,但它确实支持O_NONBLOCK,并且在任何情况下,如果在请求进行中丢失连接,都会返回EIO。

远程文件系统存在一个基本问题,一方面,为了使性能保持在可用水平,您必须缓存内容,另一方面,在多个客户端中缓存可能会导致服务器看不到的冲突

例如,NFS在默认情况下选择缓存,如果缓存是脏的,它只会挂起,直到连接恢复

表明类似的行为

从grepping sshfs'来看,它似乎根本不支持O_非块

这些都与C无关

在我看来,您最好的选择是切换到,并使用例如-o soft-o timeo=15-o retrans=1安装


在某些情况下,当网络断开时,这可能会导致数据损坏/丢失,主要是当存在多个客户端或客户端崩溃时,但它确实支持O_NONBLOCK,并且在任何情况下,如果在请求进行过程中连接丢失,它都会返回EIO。

经过一些研究后,我发现SSH挂载可以配置为在没有发生任何情况下断开连接并断开与服务器的连接

将客户端上的ServerAliveInterval X设置为在X秒后服务器无响应时断开连接

将服务器端的ClientAliveCountMax X设置为在X秒后客户端无响应时断开连接

ServerAliveCountMax Y和ClientAliveCountMax Y也可用于在断开连接之前重试Y次

应用此配置后,当连接无响应时,Linux会自动删除sshfs装载

使用此配置,写入调用将失败,首先出现输入/输出错误,然后是传输端点未连接


这足以检测到连接丢失,从而在退出之前清理混乱。

经过一番探索后,我发现SSH挂载可以配置为在没有发生任何事情的情况下断开连接并断开与服务器的连接

将客户端上的ServerAliveInterval X设置为在X秒后服务器无响应时断开连接

将服务器端的ClientAliveCountMax X设置为在X秒后客户端无响应时断开连接

ServerAliveCountMax Y和ClientAliveCountMax Y也可用于在断开连接之前重试Y次

应用此配置后,当连接无响应时,Linux会自动删除sshfs装载

与t 在他的配置中,写入调用失败,首先是输入/输出错误,然后是传输端点未连接


这足以检测到连接丢失,从而在退出之前清理混乱。

根据我的经验,不可能正确处理这种情况。大多数远程装载协议,尤其是NFS;我不知道sshfs似乎无法优雅地处理连接丢失。你在两个线程中对同一个fd调用close,并且没有同步来防止线程之间的争用情况。我建议您决定这两个线程中的哪一个应该关闭文件描述符,并确保您只在其中一个线程中关闭文件描述符。@Steven我担心这个答案。您知道支持连接丢失处理的文件系统或网络协议吗?@nos这是一个例子,我将根据最佳实现来决定哪个线程应该关闭fd。根据我的经验,不可能正确处理这种情况。大多数远程装载协议,尤其是NFS;我不知道sshfs似乎无法优雅地处理连接丢失。你在两个线程中对同一个fd调用close,并且没有同步来防止线程之间的争用情况。我建议您决定这两个线程中的哪一个应该关闭文件描述符,并确保您只在其中一个线程中关闭文件描述符。@Steven我担心这个答案。您知道支持连接丢失处理的文件系统或网络协议吗?@nos这是一个示例,我将根据最佳实现fwiw来决定哪个线程应该关闭fd。sshfs源代码有一个名为sftp_error_to_errno的函数,这似乎意味着如果在服务系统调用时连接丢失,它可以返回Econaborted,但是我没有足够的ssh经验来确定。FWIW sshfs源代码有一个名为sftp_error_to_errno的函数,这似乎意味着如果在服务系统调用时连接丢失,它可以返回ECONNABORTED,但是我没有足够的ssh经验来确定。