【问题标题】:Same file descriptor after fork()fork() 之后的文件描述符相同
【发布时间】:2015-07-25 10:21:51
【问题描述】:

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

在“Linux 编程接口”24.2.1 (p517) 中:

当一个 fork() 被执行时,孩子收到所有的重复 父文件描述符。这些复制品的制作方式 的 dup(),这意味着对应的描述符在父和 孩子引用相同的打开文件描述。

当我运行相同的代码时:

#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() 创建父文件描述符的副本是什么意思?
  2. 当两个进程(父进程和子进程)同时对同一个文件描述符执行 fstat() 之类的操作时,是否存在争用?
  3. 如果两个进程同时执行 fstat() 并且两个不同的文件描述符指向同一个文件呢?

【问题讨论】:

  • this 相关问题可能会有所帮助

标签: fork file-descriptor contention


【解决方案1】:

当您看到短语“复制文件描述符”时,您需要将其理解为“创建一个新的文件描述符,该文件描述符指向另一个指向的相同事物”。

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

在 fork 的情况下,您必须记住文件描述符的含义包含在进程中。许多进程都有一个有效的 fd 3,但它们并不都引用同一个对象。使用 fork,你有一个 fd 3 的副本,它也是 fd 3,但在不同的过程中,所以那些 3 不是本质上相同的;它们是相同的,因为 fork 做了一个副本。

您可以关闭 fd 并在子进程中打开不同的文件,您仍然会有两个 fd 3 有效的进程,但它们不再是同一事物的副本。或者您可以让子级复制 fd 3 以获取 fd 4,然后关闭 fd 3,然后您的父级中的 fd 3 和子级中的 fd 4 都指向同一个对象。

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

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

相比之下,如果你open同一个文件两次,你会得到两个引用同一个文件的文件描述符,但是通过不同打开的文件描述,所以他们有独立的标志和寻找位置。

fstat 是一个只读操作,我看不出你在为它想象什么样的“争用”。

【讨论】:

  • 感谢您的清晰解释,我没有考虑到文件描述符的编号是进程本地的。
猜你喜欢
  • 2015-09-14
  • 2012-07-28
  • 2012-10-16
  • 2014-02-26
  • 1970-01-01
  • 2020-07-19
  • 2011-05-15
  • 1970-01-01
  • 2014-07-14
相关资源
最近更新 更多