使用 FIFO 与临时文件或管道的目的是什么?

Tim*_*Tim 2 pipe ipc fifo mkfifo

来自 APUE

FIFO 可用于在一系列 shell 命令中复制输出流。这可以防止将数据写入中间磁盘文件(类似于使用管道避免中间磁盘文件)。

但是管道只能用于进程之间的线性连接,而 FIFO 有一个名称,因此它可以用于 非线性连接

考虑一个需要处理过滤输入流两次的过程。

mkfifo fifo1
prog3 < fifo1 &
prog1 < infile | tee fifo1 | prog2
Run Code Online (Sandbox Code Playgroud)

我们创建 FIFO,然后在后台启动 prog3,从 FIFO 中读取。然后我们启动 prog1 并使用 tee 将其输入发送到 FIFO 和 prog2。

  1. FIFO 如何“在一系列 shell 命令中复制输出流”?这不是由teeFIFO 来完成的吗?

  2. 在示例中,mkfifo fifo1在当前目录中创建一个文件,并且fifo1似乎可以用常规文件替换。那么FIFO“防止将数据写入中间磁盘文件”的意义何在?

  3. 进程之间的“线性连接”和“非线性连接”是什么意思?FIFO可以用于非线性连接,而管道只能用于进程之间的线性连接是什么意思?

谢谢。

Ste*_*itt 6

  1. APUE 说“FIFO可用于复制输出流”,但并不是说 FIFO 实际上复制了输出流。正如您所指出的,复制是tee在示例中完成的。

  2. mkfifo创建一个 FIFO,它在包含目录中作为“文件”可见;但是写入 FIFO 与写入文件不同,因为数据永远不会到达磁盘。管道,无论命名还是其他,不提供数据存储,它们提供通信通道;如果没有接收器,管道的写入端无法写入数据,管道只是传递数据,而不存储它。(在大多数系统中的管道由小内核缓冲区的支持,以提高性能,但是这是一个实现细节。)

  3. 进程之间的线性连接是管道,可以表示为线性图。在示例中,您可以将最后一行表示为

    infile ? prog1 ? tee fifo1 ? prog3
    
    Run Code Online (Sandbox Code Playgroud)

    这是线性的,但如果你试图表示整个链,减少到处理元素,你需要

    infile ? prog1 ? prog2
                   ? prog3
    
    Run Code Online (Sandbox Code Playgroud)

    这是非线性的(图中有一个节点,prog1,它有两个出口节点)。

  • 管道(FIFO 或其他)不保存数据,它在进程之间传输数据。例如,您可以通过运行`mkfifo fifo &amp;&amp; seq 1 1000000 | tee fifo`。最初您不会看到任何输入,因为 FIFO 在其两端都打开之前不会开始接受数据。运行“head fifo”,您将看到管道的“seq”端输出一堆数字,然后以退出代码 141 停止,*即*“SIGPIPE”(128 + 13):输出给出指示用于 FIFO 的内核缓冲区大小,最多几十 KB。这就是管道使用的所有内存。 (2认同)