5

我觉得这是一个我认为理所当然的话题。在过去,我实际上只是关闭了尽可能多的文件描述符“因为我被告知”。大多数情况下,这很有效,但偶尔我会遇到一些不可预测的行为。

因此,我想问一下 - 调用 dup / dup2 后关闭文件描述符的规则是什么?

假设我想表演cat < in > out

fd[IN] = open("in", O_RDONLY);
saved_stdin = dup(STDIN_FILENO);
dup2(fd[IN], STDIN_FILENO);
close(fd[IN])

fd[OUT] = open("out", O_WRONLY | O_CREAT | O_TRUNC, 0644);
saved_stdout = dup(STDOUT_FILENO);
dup2(fd[OUT], STDOUT_FILENO);
close(fd[OUT])


// Later on when I want to restore stdin and stdout
dup2(saved_stdin, STDIN_FILENO);
close(saved_stdin);
dup2(saved_stdout, STDINOUT_FILENO);
close(saved_stdout);

这是正确的还是我应该关闭更多的文件描述符?

4

2 回答 2

1

规则确实很简单。对于这两种dup()变体,确实如此:

  • 源 fd 保持打开状态,一旦不再需要就必须关闭。

  • 目标文件描述符,

    • 使用时dup(),始终是未使用的
    • 使用时dup2(),隐式关闭并替换为源 fd 的副本。
  • 当不再需要新的目标 fd 时,必须关闭它。

源 fd 指的是要复制的文件描述符,而目标 fd 是新的文件描述符。

int new_fd = dup(source_fd);
dup2(source_fd, new_fd);

所以是的,您的代码会执行必要的关闭,而不是不需要的。

于 2019-04-20T08:20:31.000 回答
0

这些数字来自 CSAPP System-Level:

图 2:重定向 IO 之前

dup2(4,1);

图 1:重定向 IO 之后

请注意,在调用 dup2 之后, refcntoffd 1已更改为 0。

根据linux手册close中的描述。它说:

如果文件描述符是对已使用 unlink(2) 删除的文件的最后引用,则删除该文件。

close用于减少打开文件的引用。我们dup用来创建一个新的fd会增加打开文件的refcnt。当我们调用close函数时,它并没有立即关闭文件,它只是减少了文件的引用计数。当 refcnt 为 0 时,文件将被关闭/删除。

所以它真的很像内存管理的引用计数。

于 2021-12-08T06:13:08.597 回答