fork() 后相同的文件描述符

Same file descriptor after fork()

我试图了解调用 fork() 后复制文件描述符的含义及其对争用的可能影响。

在 "The Linux Programming Interface" 24.2.1 (p517) 中:

When a fork() is performed, the child receives duplicates of all of the parent's file descriptors. These duplicates are made in the manner of dup(), which means that corresponding descriptors in the parent and the child refer to the same open file description.

当我运行同样的代码时:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/wait.h>

int main(void) {
    char* fl = "/tmp/test_fd";
    int fd;
    fd = open(fl, O_CREAT|O_TRUNC|O_WRONLY, 0666);
    if(!fork()) {
        printf("cfd=%d\n", fd);
        _exit(0);
    } else {
        int status;
        printf("ffd=%d\n", fd);
        wait(&status);
        close(fd);
        unlink(fl);
    }
}

我得到了两个进程相同的文件描述符(数字?):ffd=3 和 cfd=3。但是当 运行 此代码使用 dup():

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main(void) {
    char* fl = "/tmp/test_fd";
    int cfd, ffd;
    ffd = open(fl, O_CREAT|O_TRUNC|O_WRONLY, 0666);
    cfd = dup(ffd);
    printf("ffd=%d\n", ffd);
    printf("cfd=%d\n", cfd);
    close(ffd);
    unlink(fl);
}

我得到了不同的文件描述符:ffd=3 和 cfd=4。

那么,我有以下问题:

  1. fork() 创建父文件描述符的 copy 是什么意思?
  2. 当两个进程(父进程和子进程)同时对同一个文件描述符执行类似 fstat() 的操作时是否存在争用?
  3. 如果两个进程同时执行 fstat() 并且两个不同的文件描述符指向同一个文件呢?

当你看到短语"duplicate a file descriptor"时,你需要将其理解为"create a new file descriptor which points to the same thing the other one is pointing to"。

所以当你复制 fd 3 时,你会得到 fd 4。它们不是同一个数字,但它们标识相同 object。

在fork的情况下,你必须记住文件描述符的含义包含在一个进程中。许多进程都有一个有效的 fd 3,但它们并不都指向相同的 object。使用 fork,你有一个 fd 3 的副本,它也是 fd 3,但在不同的过程中,所以那些 3 不是 inherently 相同;它们是相同的,因为 fork 复制了一份。

您可以关闭 fd 并在 child 进程中打开一个不同的文件,您仍然会有两个进程,其中 fd 3 是有效的,但它们不再是同一事物的副本.或者你可以让 child dup fd 3 得到 fd 4,然后关闭 fd 3,然后你在 parent 中有 fd 3,在 child 中有 fd 4 引用同样 object.

不同进程中的相同数字没有任何意义。

另请注意,文件描述符引用的 object 不是文件。在文件描述符和文件之间有一些东西,它被称为打开文件描述。 fork 和 dup 都会导致共享打开的文件描述。共享的主要结果是,当当前文件位置(由 lseek 设置或由 readwrite 提前)发生变化时,所有相关的文件描述符都会受到影响,并且当标志(如 O_NONBLOCK)被更改,所有相关的文件描述符都会受到影响。

相反,如果你open同一个文件两次,你会得到两个引用同一个文件的文件描述符,但是通过不同的打开文件描述,所以它们有独立的旗帜和寻求位置。

fstat 是一个只读操作,我看不出你在想什么样的"contention"。