代码之家  ›  专栏  ›  技术社区  ›  Fermat's Little Student

bash管道中的缓冲区在linux上是如何工作的[副本]

  •  1
  • Fermat's Little Student  · 技术社区  · 6 年前

    将一个简单的命令想象为:

    cmd1 | cmd2
    

    cmd2 开始执行

    1. 一旦 cmd1 输出一些东西
    2. 或者只有在 CMD1 完全结束和退出?

    在案例1中,当 cmd1 输出速度快于 CMD2 消耗,或者简单地说在案例2中,必须有一个用于中间输出的缓冲区。

    1. 缓冲区在哪里?是在内存中还是在磁盘上?
    2. 是否可以配置缓冲区的位置和大小?
    3. 当缓冲区不够大时会发生什么?
    2 回复  |  直到 6 年前
        1
  •  3
  •   Wyzard    6 年前

    这个 cmd2 程序立即开始运行,但每当它试图读取输入时,如果有必要,它将“阻塞”(停止并等待),直到有可用的输入为止。这是由内核自动完成的除此之外,这两个程序可以并发运行(包括同时在不同的cpu核上运行)。

    两个进程之间的缓冲区由内核保存,它在内存中(尽管可能会被调出,但我不确定)这个 违约 缓冲区的大小似乎不可配置,但程序可以为特定管道请求更大的大小,以及 那个 可通过写入 /proc/sys/fs/pipe-max-size 文件(其中 /proc ,实际上不是磁盘上的文件;而是访问内核中设置的虚拟文件。) this question 更多信息。

    如果 cmd1 尝试写入但缓冲区已满,它将阻塞,直到缓冲区中有一些空间可用(当 CMD2 读取一些缓冲数据)。所以如果 cmd1 如果生产速度太快,它将自动被减慢,因为必须等待 CMD2 消耗输出。

    如果缓冲区很小,程序在等待时可能会更频繁地阻塞,这会使它们需要更长的时间才能完成,因为它们将花费更多的时间等待。

    一般来说,大多数管道可能分为两类:

    • cmd1 产生的输出比 CMD2 使用它:缓冲区通常已满(或接近它),并且 CMD1 在尝试写的时候经常阻塞,这会减慢速度以匹配 CMD2 . CMD2 能够全速运行,因为输入总是在缓冲区中可用,所以它很少在读取时阻塞。
    • cmd2 消耗输入的速度比 CMD1 产生它:缓冲区通常为空(或接近它),并且 cmd2 在尝试阅读时经常会遇到障碍,这会减慢阅读速度,使其与 CMD1 . cmd1 能够全速运行,因为总是有空间可用于写入缓冲区,所以它很少需要阻塞写入。
        2
  •  2
  •   that other guy    6 年前
    • cmd1 cmd2 并行运行,两个都立即启动
    • 如果 CMD1 速度越快,它将阻止对管道的写入。它不会继续写,也不需要额外的缓冲区空间。
    • 如果 cmd2 速度更快,它将阻止对管道的读取
    • 如果 CMD1 首先出口,管道关闭, cmd2 将其解释为文件结束并停止
    • 如果 cmd2 首先,管道将关闭, CMD1 下次写入时将收到一个sigpipe,通常会杀死它。
    • 管道本身有4096字节由posix保证,并且(目前)在linux上有65536字节的内存缓冲空间。你不会经常改变它如果需要更多空间,请使用临时文件。