关于SVN中文件描述符重用引发文件损坏的技术疑问
关于SVN代码中文件描述符处理的疑问解答
看到的SVN源码注释:
/* The following makes sure that file descriptors 0 (stdin), 1
(stdout) and 2 (stderr) will not be "reused", because if
e.g. file descriptor 2 would be reused when opening a file, a
write to stderr would write to that file and most likely
corrupt it. */
对应的源码实现:
if ((fstat(0, &st) == -1 && open("/dev/null", O_RDONLY) == -1) || (fstat(1, &st) == -1 && open("/dev/null", O_WRONLY) == -1) || (fstat(2, &st) == -1 && open("/dev/null", O_WRONLY) == -1)) { if (error_stream) fprintf(error_stream, "%s: error: cannot open '/dev/null'\n", progname); return EXIT_FAILURE; }
问题1:重用文件描述符为何会导致文件损坏?
操作系统分配文件描述符时,会优先选用当前未被使用的最小编号。比如如果stderr对应的fd=2被关闭了,后续调用open()打开普通文件时,系统很可能把fd=2分配给这个新文件。这时程序里如果还有代码向stderr(也就是现在的fd=2)写入错误信息、日志,这些内容会直接写到那个普通文件里,打乱文件原有内容结构,最终导致文件损坏。
问题2:如何使用文件描述符2(stderr)打开文件?
准确来说是把目标文件关联到fd=2,常见两种实现方式:
- 方法一:先关闭fd=2,再调用
open()打开目标文件。系统会自动把最小可用的fd(也就是2)分配给新文件,此时fd=2就指向这个文件。 - 方法二:先打开目标文件得到临时fd,再用
dup2()将临时fd复制到fd=2。示例代码:int tmp_fd = open("target_file", O_WRONLY | O_CREAT, 0644); if (tmp_fd != -1) { dup2(tmp_fd, 2); // 将临时fd的关联复制到fd=2 close(tmp_fd); // 临时fd不再需要,关闭释放 }
问题3:打开文件的操作为何会影响对stderr的写入?
如果stderr对应的fd=2处于未使用状态(比如被提前关闭),调用open()打开新文件时会复用这个fd。此时fd=2对应的已经不是原来的标准错误输出(通常是终端),而是新打开的文件。程序里所有向stderr(fd=2)的写入操作,都会被操作系统导向这个新文件,而不是原本的标准错误输出,自然就改变了stderr的写入行为。
内容的提问来源于stack exchange,提问作者user15787088
相关产品推荐
相关产品推荐

