gpt4 book ai didi

linux - 使用 Linux pipe() 的进程编程模型

转载 作者:太空狗 更新时间:2023-10-29 11:39:37 25 4
gpt4 key购买 nike

来自 http://pubs.opengroup.org/onlinepubs/009604599/functions/pipe.html :

The pipe() function shall create a pipe and place two file descriptors, one each into the arguments fildes[0] and fildes[1], that refer to the open file descriptions for the read and write ends of the pipe.

有一个父进程向其子​​进程写入数据的例子:

int fildes[2];
const int BSIZE = 100;
char buf[BSIZE];
ssize_t nbytes;
int status;


status = pipe(fildes);
if (status == -1 ) {
/* an error occurred */
...
}


switch (fork()) {
case -1: /* Handle error */
break;


case 0: /* Child - reads from pipe */
close(fildes[1]); /* Write end is unused */
nbytes = read(fildes[0], buf, BSIZE); /* Get data from pipe */
/* At this point, a further read would see end of file ... */
close(fildes[0]); /* Finished with pipe */
exit(EXIT_SUCCESS);


default: /* Parent - writes to pipe */
close(fildes[0]); /* Read end is unused */
write(fildes[1], "Hello world\n", 12); /* Write data on pipe */
close(fildes[1]); /* Child will see EOF */
exit(EXIT_SUCCESS);
}
  1. 我想知道使用管道与 child 通信的 parent 如何确保 child 不会在 parent 运行 write 之前运行 read(),而 child parent 还没写完就读完了?

  2. 我想知道在父级中创建的管道是否可以用于 parent 和 child 之间的双向沟通​​,或者只是一种方式 parent 对 child 不是另一种方式吗?

    如果子进程可以通过管道向父进程发送数据,那么程序长什么样子?

  3. 管道是否像真正的管道一样有两端。菲尔德斯 [0] 和菲尔德斯 [1]分别用来表示两端?

    如果管道是双向的,读端和写端是什么意思关于,即哪个读(写), parent 还是 child ?

谢谢和问候!

最佳答案

  1. 除非您指定O_NONBLOCK,否则read 将阻塞并等待数据可用。所以没关系;如果数据尚不可用,它将等待。
  2. 不,管道不是双工的。如果你想要双向通信,你应该制作两个管道(总共会给你四个文件描述符)。 fildes[0] 始终是读取(输出)端,fildes[1]写入(输入)结束。所以你完全按照你所做的那样设置一个管道(父级获得写入端,子级获得读取端,因此父级可以发送给子级),然后以相反的方式设置另一个管道(你让家长保留阅读端,给 child 写端)。
  3. fildes[0]fildes[1] 确实代表管道的末端,但它们不可互换。一个用于将数据“放入”管道,另一个用于从管道“取出”数据。

如果您需要更多说明,请随时询问;我意识到这可能会让新手感到困惑。

更新以回答评论中的问题:

  1. 任何进程都可以调用pipe(),它的子进程将继承它接收到的文件描述符(除非你关闭它们)。也就是说,它们通过多次 fork() 调用存活下来。因此,如果您愿意,您可以编写一个程序,将文件描述符提供给孙子、曾孙等。
  2. 当然,两个兄弟进程可以这样通信。父级调用 pipe() 来创建对(如果需要双向通信,则为两对),然后 fork 两次。然后,您可以让一个 child 使用 fildes[0],让另一个 child 使用 fildes[1]。父级不应使用任何文件描述符。瞧!具有共同 parent 的 child 之间的交流。这个简单(尽管可能不直观)的功能非常强大。这看起来类似于下面的示例。
  3. fork() 想象成一台克隆机。在进入克隆机之前,您使用 pipe() 制作一对使用特殊 secret 频率的匹配对讲机。一个只能传输;另一个只能接收。当你使用克隆机时,你会出现两个副本(原始的,即 parent ,和克隆的,即 child )。每个副本现在都携带一对相同的匹配对讲机。如果原始人破坏了他的“接收”设备而克隆人破坏了他的“传输”设备,那么原始人可以使用对讲机与克隆人交谈(但反之则不行)。

    但是你看,这里的关键思想不是 pipe() 连接两个进程(尽管这是它的主要用途),而是它是在 fork()。您可以多次重新进入克隆机并获得许多对讲机,因此定义“谁在与谁通话”(哪些进程通过管道连接)不是克隆机功能的特定方面或对讲机。

    相反,它取决于最终实际使用哪些端点的人,这完全由您控制。如果你愿意,你可以让 child 关闭两个端点(摧毁两个对讲机),这样 parent 就可以自言自语了(这很愚蠢,可能没有用,但可能) .我意识到这有点离题,但我正在尝试传达基本思想的工作原理,以便您了解管道可能实现的领域。

兄弟进程与管道(单向)对话的示例:

int fildes[2];
int status;

status = pipe(fildes);
if (status == -1) { ... }

// first fork
switch (fork()) {
case -1:
// handle error
break;

case 0:
// child 1 (with the writing end -- close the writing end)
close(fildes[0]);
// your logic for child 1 here, using fildes[1] to write
return;

default:
// not child 1: close the writing end
close(fildes[1]);
break;
}

// second fork
switch (fork()) {
case -1:
// handle error
break;

case 0:
// child 2 (with the reading end)
// your logic for child 2 here, using fildes[0] to read
return;
}

// still in the parent
// logic for the common parent here, after forking both children

关于linux - 使用 Linux pipe() 的进程编程模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6905843/

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