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