【问题标题】:Why fork() close one of the file descriptor by dup2()为什么 fork() 通过 dup2() 关闭文件描述符之一
【发布时间】:2014-07-14 18:37:46
【问题描述】:

我编写代码来了解 dup2()。

int main(int argc, char* argv[]) {
    FILE *fp = fopen(argv[1],"r");
    int fdold,fdnew;
    fdold = fileno(fp);
    fdnew = dup2(fdold,fdnew);
    while (1) {
        sleep(1000);
    }
}

lsof 显示 2 个打开的文件描述符(/workspace/source/throw.cpp 是传入的参数)

/workspace/source/thread$ lsof -p 20779
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
dup2    20779  wto  cwd    DIR    8,1     4096 946031 /workspace/source
dup2    20779  wto  rtd    DIR    8,1     4096      2 /
dup2    20779  wto  txt    REG    8,1     8672 950259 /workspace/source/dup2
dup2    20779  wto  mem    REG    8,1  1852120 135869 /lib/x86_64-linux-gnu/libc-2.17.so
dup2    20779  wto  mem    REG    8,1   149312 135845 /lib/x86_64-linux-gnu/ld-2.17.so
dup2    20779  wto    0u   CHR  136,4      0t0      7 /dev/pts/4
dup2    20779  wto    1u   CHR  136,4      0t0      7 /dev/pts/4
dup2    20779  wto    2u   CHR  136,4      0t0      7 /dev/pts/4
dup2    20779  wto    3r   REG    8,1      653 951057 /workspace/source/throw.cpp
dup2    20779  wto *767r   REG    8,1      653 951057 /workspace/source/throw.cpp

但是,当我将它 fork() 到 2 个进程(代码如下)时,只打开了一个 /workspace/source/throw.cpp。

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

int main(int argc, char* argv[]) {
    FILE *fp = fopen(argv[1],"r");
    int fdold,fdnew;
    fdold = fileno(fp);
    //fcntl(F_DUPFD_CLOEXEC,fdold);
    fdnew = dup2(fdold,fdnew);
    pid_t pid;
    if ((pid = fork()) < 0) {
        exit(-1);
    } else if (pid > 0) {
        waitpid(pid, WNOHANG, NULL);
        printf("parent exit\n");    
    } else {
        while (1) {
            sleep(1000);
        }
    }
    return 0;
}
  1. 问题 1:是什么导致 dup()d fd 被关闭?
  2. 问题2:我在手册中查看了FD_CLOEXEC,但没有通过fcntl() 设置它。 fopen() 是否自动设置它?这个标志不仅会影响 fork 还会影响 exec 家族吗?
  3. 问题3:我把dup2换成dup后,结果显示2个fds符合我的预期。 正如手册所说:

    “dup2() 使 newfd 成为 oldfd 的副本,必要时先关闭 newfd”。

    如果newfd已经打开,是否意味着在dup之前关闭newfd?

【问题讨论】:

    标签: c linux fork dup


    【解决方案1】:

    您的代码有一个错误(在设置之前使用fdnew 的值),因此它的行为将是不可预测的。在您尝试了解程序在做什么之前修复错误。另外,你应该检查dup2的返回值,看看它是否成功。

    【讨论】:

    • 你是对的。我没有正确理解 dup,fdnew 和 fdold 必须是有效的文件描述符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多