管道外壳程序如何平衡其输出/输入速率?

Red*_*Red 11 shell pipe system-calls stdout stdin

可能的重复:
Bash while 循环和从管道读取

我来自 Web 编程背景,发现自己对使用本地 shell 的一个特性很感兴趣。我知道当程序从文件中读取时,它可以以任何必要的速率读取。但是我很想知道,当一个程序通过管道接收其他程序的输入并且无法实时处理它时,它是如何工作的?

一个很好的例子是视频编码。假设我将解码器指向视频文件,然后它的输出作为编码器的输入通过管道输入。解码视频的总大小超过 ram+swap,所以我想没有办法完全缓冲它。我发现了对 stdin 和 stdout 的读写调用,但我很想知道当这个例子的编码器不能同时处理所有数据时实际发生了什么。它是否以某种方式通知解码器所需的速率?解码器程序是否需要专门为这样的信号准备并相应地修改它的处理速度?如果没有,最后如何平衡?

Sha*_*off 5

当写入器写入管道并且管道已满(其大小限制为几千字节)时,其进程会阻塞,直到其中一个读取器释放一些空间。类似地,当读取器从管道读取时,它的进程会阻塞,直到那里有东西。

还有异步写入和读取,程序员可以使用它们来排队这些读取和写入。

我强烈建议阅读Beej 的 Gudes,从 Beej 的Unix 进程间通信指南开始

你用两个参数调用它,第一个是作者的睡眠时间,第二个是读者的睡眠时间。尝试用 args0 33 0

#!/bin/sh
write_sleep=$1
read_sleep=$2
writer(){
  echo writing output >&2
  echo hi
  sleep $write_sleep
  echo writing output >&2
  echo hi
  sleep $write_sleep
  echo writing output >&2
  echo hi
  sleep $write_sleep
}
reader(){
  while true; do
    echo getting input >&2
    read input
    [ $input ] || { echo input is empty >&2 &&  break; }
    echo $input
    sleep $read_sleep
  done
}

writer | reader
Run Code Online (Sandbox Code Playgroud)