【问题标题】:How does buffer in bash pipe work on linux? [duplicate]bash 管道中的缓冲区如何在 linux 上工作? [复制]
【发布时间】:2018-12-29 08:14:05
【问题描述】:

想一个简单的命令如下:

cmd1 | cmd2

cmd2 是否开始执行

  1. 只要cmd1 输出一些东西
  2. 或仅当cmd1 完全完成并退出?

如果cmd1 的输出速度快于cmd2 的消耗速度,或者只是在情况2 中,则必须有一个用于中间输出的缓冲区。

  1. 该缓冲区位于何处?它是在内存中还是在磁盘上?
  2. 是否可以配置缓冲区的位置和大小?
  3. 缓冲区不够大会怎样?

【问题讨论】:

标签: linux bash pipe


【解决方案1】:
  • cmd1cmd2 并行运行,都立即启动
  • 如果cmd1 更快,它将阻止对管道的写入。它不会继续写入,也不需要额外的缓冲区空间。
  • 如果cmd2 更快,它将阻止对管道的读取
  • 如果cmd1 先退出,管道关闭,cmd2 将其解释为文件结束并停止
  • 如果 cmd2 先退出,管道将关闭,cmd1 将在下次写入时收到 SIGPIPE,通常会终止它。
  • 管道本身具有 POSIX 保证的 4096 字节,并且(当前)在 Linux 上具有 65536 字节的内存缓冲区空间。你不会经常改变它。如果您需要更多空间,请使用临时文件。

【讨论】:

  • cmd1 不一定会退出,但是,当它到达其标准输入的末尾时。
【解决方案2】:

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 能够全速运行,因为始终有空间可用于写入缓冲区,因此它很少需要阻塞写入。

【讨论】:

    猜你喜欢
    • 2015-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多