C中的管道,用于读取stdin的缓冲区



我正在努力理解这个答案。特别是,数据是如何跨流程流动的?

我假设输入流通过与管道连接的输出流经子级的输入,然后由父级通过管道输出收集。然而,在循环的新一轮并在子级中执行命令之前,读取的数据会发生什么?

数据是否在父进程中缓冲(不知怎么的?我想知道是什么原因造成的(,然后这个缓冲区在fork()之后被复制并传递给子进程,然后子进程将保存的输入传递给exec()

编辑-附加方面:

(在我给出的例子中,当调用pipe()时,新管道在循环的每一圈都会创建,并填充新的描述符。我创建了一个工作修改,在循环之外创建描述符表并重新填充。它如何影响以前从执行的命令中读取的数据?它存储在哪里,当创建新管道和新文件描述符时iptor存储在重用表中?(

有一个缓冲区与管道关联。

如果缓冲区未满,写入操作将返回,程序将继续。

但是缓冲区可能会被填满。如果写入无法完成,则会导致部分写入(提供写入量(或阻塞,直到写入可以完成(即,当某个东西最终从另一端读取时(。

试图从空管道中读取数据的读取器通常会阻塞,直到数据可用。如果描述符被设置为非阻塞,则读取将返回错误EWOULDBLOCK或EAGAIN。

select和类似机制可用于检测何时可以安全地执行读取或写入而不阻塞。

管道的每一端都可以独立闭合。只有关闭文件描述符的所有副本后,结束才会关闭。这包括继承的副本。一种常见的情况是子级从其父级继承管道。父级将关闭其中一个描述符,子级将关闭另一个描述符。这使得一个进程能够写入管道,另一个进程则能够从中读取。(双向通信需要两个管道或一个套接字。(

如果读者退出会发生什么?默认情况下,写入闭合管道会产生SIGPIPE信号。默认情况下,这会终止写入过程。这通常非常有用。例如,考虑在非常长的流上使用head的情况。但它并不总是有用的。有时,你想发现并处理这种情况。幸运的是,通过使用通常的机制处理信号或忽略信号,这是完全可配置的。如果忽略,写入操作将失败,错误代码为EPIPE。

系统之间的行为会有差异。例如,Windows没有信号*,select无法在管道上工作。(不过,它确实适用于套接字。(但它也提供了执行异步I/O的替代方法。

最新更新