管道在 Linux 中的工作原理

Bra*_*don 28 kernel pipe

我一直在阅读有关如何在 Linux 内核中实现管道的信息,并希望验证我的理解。如果我不正确,将选择具有正确解释的答案。

  • Linux 有一个名为 pipefs 的 VFS,它安装在内核中(不是在用户空间中)
  • pipefs 有一个超级块,安装在它自己的根 ( pipe:) 上,旁边是/
  • 与大多数文件系统不同,pipefs 不能直接查看
  • pipefs 的入口是通过pipe(2)系统调用
  • pipe(2)shell 用于与|操作员(或从任何其他进程手动)进行管道传输的系统调用在 pipefs 中创建一个新文件,该文件的行为与普通文件非常相似
  • 管道运算符左侧的文件已stdout重定向到在 pipefs 中创建的临时文件
  • 管道运算符右侧的文件已stdin设置为 pipefs 上的文件
  • pipefs 存储在内存中,通过一些内核魔法,不应该被分页

这是对管道(例如ls -la | less)如何运作的解释非常正确吗?

我不明白的一件事是像 bash 这样的东西如何设置一个进程stdinstdoutpipe(2). 我还没有找到任何关于它的信息。

Gre*_*ill 24

到目前为止,您的分析总体上是正确的。shell 可能将进程的 stdin 设置为管道描述符的方式可能是(伪代码):

pipe(p) // create a new pipe with two handles p[0] and p[1]
fork() // spawn a child process
    close(p[0]) // close the write end of the pipe in the child
    dup2(p[1], 0) // duplicate the pipe descriptor on top of fd 0 (stdin)
    close(p[1]) // close the other pipe descriptor
    exec() // run a new process with the new descriptors in place
Run Code Online (Sandbox Code Playgroud)

  • 在`pipe()`中创建文件描述符时,调用者无法选择文件描述符的数值。`dup2()` 调用允许调用者将文件描述符复制到特定的数值(需要,因为 0、1、2 是 stdin、stdout、stderr)。这相当于“直接分配给标准输入”的内核。请注意,C 运行时库全局变量 `stdin` 是一个 `FILE *`,它与内核无关(尽管它被初始化为连接到描述符 0)。 (3认同)