【发布时间】:2018-12-29 08:14:05
【问题描述】:
想一个简单的命令如下:
cmd1 | cmd2
cmd2 是否开始执行
- 只要
cmd1输出一些东西 - 或仅当
cmd1完全完成并退出?
如果cmd1 的输出速度快于cmd2 的消耗速度,或者只是在情况2 中,则必须有一个用于中间输出的缓冲区。
- 该缓冲区位于何处?它是在内存中还是在磁盘上?
- 是否可以配置缓冲区的位置和大小?
- 缓冲区不够大会怎样?
【问题讨论】:
想一个简单的命令如下:
cmd1 | cmd2
cmd2 是否开始执行
cmd1 输出一些东西cmd1 完全完成并退出?如果cmd1 的输出速度快于cmd2 的消耗速度,或者只是在情况2 中,则必须有一个用于中间输出的缓冲区。
【问题讨论】:
cmd1 和 cmd2 并行运行,都立即启动cmd1 更快,它将阻止对管道的写入。它不会继续写入,也不需要额外的缓冲区空间。cmd2 更快,它将阻止对管道的读取cmd1 先退出,管道关闭,cmd2 将其解释为文件结束并停止cmd2 先退出,管道将关闭,cmd1 将在下次写入时收到 SIGPIPE,通常会终止它。【讨论】:
cmd1 不一定会退出,但是,当它到达其标准输入的末尾时。
cmd2 程序立即开始运行,但每当它尝试读取输入时,它会在必要时“阻塞”(停止并等待),直到有一些可用为止。这是由内核自动完成的。除此之外,这两个程序可以同时运行(包括同时在不同的 CPU 内核上)。
两个进程之间的缓冲区由内核持有,它在内存中(尽管它可能会被分页——我不确定)。缓冲区的 default 大小似乎不可配置,但程序可以为特定管道请求更大的大小,并且 that 的限制可通过写入/proc/sys/fs/pipe-max-size 文件(位于/proc 中,实际上并不是磁盘上的文件;它是访问内核中设置的虚拟文件。)有关更多信息,请参阅this question。
如果cmd1 尝试写入但缓冲区已满,它将阻塞,直到缓冲区中有可用空间(当cmd2 读取一些缓冲数据时会发生这种情况)。因此,如果 cmd1 产生输出的速度过快,它会自动减慢,因为必须等待 cmd2 消耗输出。
如果缓冲区很小,程序在等待它时可能会更频繁地阻塞,这会使它们需要更长的时间才能完成,因为它们会花费更多的时间等待。
一般来说,大多数管道可能分为两类:
cmd1 产生输出的速度比cmd2 消耗它的速度快:缓冲区通常是满的(或接近它),cmd1 在尝试写入时经常阻塞,这会减慢它的速度以匹配cmd2 的速度。 cmd2 能够全速运行,因为输入总是在缓冲区中可用,因此它很少需要在读取时阻塞。cmd2 消耗输入的速度比cmd1 生成它的速度快:缓冲区通常是空的(或接近它),并且cmd2 在尝试读取时经常阻塞,这会减慢它的速度以匹配cmd1 的速度。 cmd1 能够全速运行,因为始终有空间可用于写入缓冲区,因此它很少需要阻塞写入。【讨论】: