注册

Linux报 “invalid file descriptor” 异常的原因以及解决办法

报错信息 "invalid file descriptor" 表示系统在尝试访问一个不存在或已关闭的文件描述符时发生了错误。下面我们详细来讲解一下这个问题的原因和解决办法。

原因

  1. 文件描述符被关闭

Linux系统中,文件描述符是一种与打开的文件之间的联系,通常通过调用open()、creat()、accept()等函数来建立。当文件描述符被关闭,那么这个文件描述符就会变成无效的。当再次访问它时,就会出现 "invalid file descriptor" 的错误。

  1. 文件描述符被重用

在多线程或多进程的程序中,如果一个线程或进程关闭了一个文件描述符,而另一个线程或进程正在使用它,就会出现 "invalid file descriptor" 的错误。这是因为关闭一个文件描述符后,该描述符可能会被重新分配给另一个文件,在使用时就会出现错误。

  1. 进程崩溃

如果程序正在运行并突然崩溃,那么其中已经打开的文件描述符就会变得无效。当程序再次运行时,尝试使用这些描述符将会出现 "invalid file descriptor" 的错误。

解决办法

解决 "invalid file descriptor" 错误的方法主要包括以下两种。

  1. 检查代码逻辑

当出现 "invalid file descriptor" 错误时,首先要检查程序的逻辑,尤其是在多线程或多进程场景下,需要确保关闭文件描述符的线程或进程不与正在访问这个描述符的其他线程或进程相冲突。

  1. 使用dup()或dup2()函数重新分配文件描述符

dup() 和 dup2() 函数都可以用来创建新的文件描述符,而不是直接使用已关闭的描述符。dup() 函数会将当前文件描述符映射到一个新的文件描述符上。dup2() 函数会将一个文件描述符移动到另一个文件描述符上,如果之前存在这个描述符,则它会被关闭。这样,我们就可以避免使用已关闭的文件描述符。

下面是一个使用dup()函数重新分配文件描述符的示例代码:

#include 
#include 
#include 
#include 

int main(void){
    int fd1, fd2, n;
    char buf[100];

    fd1 = open("test.txt", O_RDONLY); 
    if(fd1 == -1){
        perror("open test.txt failed");
        exit(-1);
    }
    printf("fd1 = %d\n", fd1);

    fd2 = dup(fd1); // 使用dup()函数重新分配文件描述符
    if(fd2 == -1){
        perror("dup fd1 failed");
        exit(-1);
    }
    printf("fd2 = %d\n", fd2);

    //使用新的文件描述符 fd2 读取文件
    while ((n = read(fd2, buf, 100)) > 0) {
        write(STDOUT_FILENO, buf, n);
    }

    close(fd1);
    close(fd2);

    return 0;
}

上述代码中,我们首先打开了一个文件 "test.txt",然后使用dup()函数重新分配了一个新的文件描述符 fd2。最后我们通过 fd2 读取文件内容并打印到终端。

通过这种方法,我们就避免了 "invalid file descriptor" 的错误。