【问题标题】:Unix - how to change buffer strategy with a pseudo terminal? [closed]Unix - 如何使用伪终端更改缓冲区策略? [关闭]
【发布时间】:2017-02-14 10:30:53
【问题描述】:

我是 Linux 新手,我正在尝试掌握管道和缓冲区的工作原理。 我读到,如果我们在终端中输入以下内容:

command1 | command2 

当缓冲区包含 4K 数据时,缓冲区将被刷新到标准输出。 来自stackoverflow的另一篇文章 How to make output of any shell command unbuffered?

我发现可以使用伪终端“关闭”缓冲区或将缓冲区策略更改为行缓冲。在这种情况下,伪终端实际上​​是如何工作的?为什么可以使用伪终端来改变缓冲策略?

谢谢!

【问题讨论】:

  • 你在说什么“缓冲区”?标准 C stdout 缓冲区,例如由printf 并且默认行缓冲?管道本身使用的低级缓冲区?其他一些内核级缓冲区?

标签: c unix pipe


【解决方案1】:

使用伪终端“有效”的原因是 stdio 库查看输出是否将发送到终端以决定使用哪种缓冲策略。伪终端让它认为它正在与终端对话,因此它选择终端策略而不是“管道”策略。

【讨论】:

  • 这是否意味着当我的输出进入终端时,它总是行缓冲?
  • 在这种情况下,行缓冲是默认设置,但程序可以选择其他选项——在 UNIXy 系统上,请参阅“man setvbuf”了解详细信息。
【解决方案2】:

您的简单命令涉及很多“缓冲区”。

  1. 命令代码中可能存在一些缓冲。例如,如果使用 C I/O,那么默认情况下,在输出上会有一个缓冲区。如果命令使用系统 I/O,则输出没有缓冲。
  2. 管道提供某种缓冲,它是否提供了生产者/消费者语义。字节被存储到管道中,直到一次读取读取它们。
  3. 管道的第一个命令可以从 tty 读取,最后一个命令可以写入 tty,并且 tty 有一个可以使用缓冲区的行规程。

从您的角度来看,作为用户,您唯一可以玩的是终端的线路规则,这样可以尽快交付所提供的输入,或者通过某种烹饪或缓冲。命令stty可以用来控制这一切。

【讨论】:

    【解决方案3】:

    当缓冲区包含 4K 的数据时,缓冲区将被刷新到标准输出。

    您可能指的是臭名昭著的PIPE_BUF POSIX 要求。这与在一定大小后刷新管道缓冲区无关。

    PIPE_BUF 要求是为了保证当多个进程各自写入少于 PIPE_BUF 到同一管道时,读取器不会看到来自不同进程的混合输入。

    假设PIPE_BUF4(尽管它要求至少是512 并且在大多数系统上默认是4096),并且两个进程写入同一个管道:

    ProcessA: write(pipe, "abcd", 4)
    ProcessB: write(pipe, "EFG", 3)
    ProcessC: read(pipe, buf, 7)
    

    由于两个进程各自写入的字节数均小于或等于4,因此接收方将获得abcdEFGEFGabcd,但不会获得abEFGcdEFabcdG

    这通常被错误地解释为“将通过另一侧的单个read() 检索小于PIPE_BUF 的单个write()”。

    【讨论】:

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