我有两个简单的程序:A
和B
. A
将首先运行,然后B
获取“stdout”A
并将其用作其“stdin”。假设我使用的是 GNU/Linux 操作系统,最简单的方法是:
./A | ./B
如果我必须描述这个命令,我会说它是一个从生产者( )获取输入(即读取A
)并写入消费者(B
)的命令。这是正确的描述吗?我错过了什么吗?
我有两个简单的程序:A
和B
. A
将首先运行,然后B
获取“stdout”A
并将其用作其“stdin”。假设我使用的是 GNU/Linux 操作系统,最简单的方法是:
./A | ./B
如果我必须描述这个命令,我会说它是一个从生产者( )获取输入(即读取A
)并写入消费者(B
)的命令。这是正确的描述吗?我错过了什么吗?
关于你的问题唯一突出的错误是你说
事实上,这两个程序几乎同时启动。如果在尝试读取时没有输入
B
,它将阻塞,直到有输入要读取。同样,如果没有人从 读取输出A
,它的写入将阻塞,直到它的输出被读取(其中一些将被管道缓冲)。唯一使参与管道的进程同步的是 I/O,即跨管道的读取和写入。如果没有写入或读取发生,那么这两个进程将完全独立运行。如果一个忽略另一个进程的读取或写入,则被忽略的进程将阻塞并最终被
SIGPIPE
信号杀死(如果写入)或在另一个进程终止时在其标准输入流(如果读取)上获得文件结束条件.描述的惯用方式
A | B
是它是一个包含两个程序的管道。第一个程序在标准输出上产生的输出可供第二个程序在标准输入上读取(“[输出]A
通过管道传输到[输入]B
”)。外壳执行所需的管道以允许这种情况发生。如果您想使用“消费者”和“生产者”这两个词,我想也可以。
这些是用 C 编写的程序这一事实无关紧要。这与 Linux、macOS、OpenBSD 或 AIX 无关。
文档中通常使用的术语是“管道”,它由一个或多个命令组成,请参见 POSIX 定义 所以从技术上讲,这是您拥有的两个命令,shell 的两个子进程(
fork()+exec()
'ed external commands 或 subshells )至于生产者-消费者部分,可以用该模式来描述管道,因为:
/proc/<pid>/fd
目录)。stdout
和消费者读取stdin
就好像它们是正在执行的单个命令,也就是它们可以在没有彼此的情况下存在。我在这里看到的不同之处在于,与其他语言中的 Producer-Consumer 不同,shell 命令使用缓冲,一旦缓冲区被填满,它们就会写入 stdout,但没有提到 Producer-Consumer 必须遵循该规则 - 仅在队列填满或丢弃时等待数据(这是管道不做的其他事情)。