调用dup/dup2后关闭文件描述符的规则是什么?
What are the rules of closing file descriptors after calling dup/dup2?
我觉得这是我为 g运行ted 选的主题。在过去,我实际上只是关闭了尽可能多的文件描述符 "because I was told to"。大多数时候这是有效的,但偶尔我 运行 会出现一些不可预知的行为。
因此,我想问一下 - 调用 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);
这是正确的还是我应该关闭更多文件描述符?
规则确实很简单。对于两个 dup()
变体,确实如此:
源 fd 保持打开状态,一旦不再需要就必须将其关闭。
目标文件描述符,
- 使用
dup()
时,始终是未使用的
- 当使用
dup2()
时,隐式关闭并替换为源 fd 的副本。
新的目标 fd 在不再需要时必须关闭。
Source fd是指要复制的文件描述符,target fd是新的文件描述符。
int new_fd = dup(source_fd);
dup2(source_fd, new_fd);
所以是的,您的代码执行必要的关闭操作,没有不需要的关闭操作。
数据来自CSAPP系统级:
Figure 2: Before Redirect IO
dup2(4,1);
Figure 1: After Redirect IO
注意 fd 1
的 refcnt
在调用 dup2 后变为 0。
根据linux manual中close
的描述。它说:
if the file descriptor was the last reference to a file which has been removed using unlink(2), the file is deleted.
close
用于减少打开文件的refcnt。我们使用 dup
创建一个新的 fd 将增加打开文件的 refcnt。当我们调用 close
函数时,它并没有立即关闭文件,它只是减少了文件的引用计数。当 refcnt 为 0 时,文件将为 close/delete。
所以它真的很像内存管理的引用计数。
我觉得这是我为 g运行ted 选的主题。在过去,我实际上只是关闭了尽可能多的文件描述符 "because I was told to"。大多数时候这是有效的,但偶尔我 运行 会出现一些不可预知的行为。
因此,我想问一下 - 调用 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);
这是正确的还是我应该关闭更多文件描述符?
规则确实很简单。对于两个 dup()
变体,确实如此:
源 fd 保持打开状态,一旦不再需要就必须将其关闭。
目标文件描述符,
- 使用
dup()
时,始终是未使用的 - 当使用
dup2()
时,隐式关闭并替换为源 fd 的副本。
- 使用
新的目标 fd 在不再需要时必须关闭。
Source fd是指要复制的文件描述符,target fd是新的文件描述符。
int new_fd = dup(source_fd);
dup2(source_fd, new_fd);
所以是的,您的代码执行必要的关闭操作,没有不需要的关闭操作。
数据来自CSAPP系统级:
Figure 2: Before Redirect IO
dup2(4,1);
Figure 1: After Redirect IO
注意 fd 1
的 refcnt
在调用 dup2 后变为 0。
根据linux manual中close
的描述。它说:
if the file descriptor was the last reference to a file which has been removed using unlink(2), the file is deleted.
close
用于减少打开文件的refcnt。我们使用 dup
创建一个新的 fd 将增加打开文件的 refcnt。当我们调用 close
函数时,它并没有立即关闭文件,它只是减少了文件的引用计数。当 refcnt 为 0 时,文件将为 close/delete。
所以它真的很像内存管理的引用计数。