gpt4 book ai didi

c - beej导流管实例讲解

转载 作者:太空宇宙 更新时间:2023-11-04 04:34:20 25 4
gpt4 key购买 nike

以下代码是beej的指南中给出的管道实现:

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

int main(void)
{
int pfds[2];
pipe(pfds);
if (!fork()) {
close(1); /* close normal stdout */
dup(pfds[1]); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
execlp("ls", "ls", NULL);
} else {
close(0); /* close normal stdin */
dup(pfds[0]); /* make stdin same as pfds[0] */
close(pfds[1]); /* we don't need this */
execlp("wc", "wc", "-l", NULL);
}
return 0;
}

我想问:

  1. 是否有可能 close(0)dup(pfds[1]) 之前执行?如果是,那么在那种情况下程序将不会按预期运行。
  2. 下面这几行代码有什么用:

    close(pfds[0]); /* we don't need this */
    close(pfds[1]); /* we don't need this */

如果没有这些行会发生什么变化?

最佳答案

Is it possible that close(0) is executed before dup(pfds[1])? If yes, then in that case the program will not behave as expected.

是的,可以在子调用dup(pfds[1]) 之前让父成功完成close(0)。但是,这不是问题。当您 fork 一个新进程时,新进程会获得父进程内存地址空间的完整副本,包括打开的文件描述符(标有 O_CLOEXEC 标志的除外 - 请参阅 fcntl(2))。因此,基本上每个进程都有自己的文件描述符私有(private)副本,并且是隔离的,可以自由地使用该副本做任何想做的事情。

因此,当父级调用close(0) 时,它只是关闭其文件描述符 0 的副本 (stdin);它不会以任何方式影响子级,它仍然具有对 stdin 的引用并且可以在需要时使用它(即使在本例中它不会)。

What is the use of the following lines of code:

close(pfds[0]); /* we don't need this */
close(pfds[1]); /* we don't need this */

最佳实践要求您应该关闭不使用的文件描述符 - close(pfds[0]) 就是这种情况。未使用的打开文件描述符会占用空间和资源,如果您不打算使用它,为什么要保持打开状态?

close(pfds[1]) 虽然更微妙一些。仅当管道缓冲区中没有更多数据时,管道才报告文件结束并且没有事件的编写器,即没有打开管道进行写入的实时进程。如果您不关闭父级中的 pfds[1],程序将永远挂起,因为 wc(1) 永远不会看到输入的结尾,因为有一个进程(wc(1) 本身)已打开管道进行写入,因此可以(但不会)写入更多数据。

Tl;DR:close(pfds[0]) 只是一种很好的做法,但不是强制性的; close(pfds[1]) 是确保程序正确性所必需的。

关于c - beej导流管实例讲解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32753483/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com