【发布时间】:2014-10-07 11:22:52
【问题描述】:
我在遍历管道定义时发现了以下语句:一个 FIFO 可以有多个读取器或多个写入器。每个写入器的字节以原子方式写入,最大大小为 PIPE_BUF(Linux 上为 4KB)。来自同时写入者的块可以交错。类似的规则适用于同时读取。我无法理解“同时作者的块可以交错”。有人可以解释吗?
【问题讨论】:
标签: c linux unix linux-kernel
我在遍历管道定义时发现了以下语句:一个 FIFO 可以有多个读取器或多个写入器。每个写入器的字节以原子方式写入,最大大小为 PIPE_BUF(Linux 上为 4KB)。来自同时写入者的块可以交错。类似的规则适用于同时读取。我无法理解“同时作者的块可以交错”。有人可以解释吗?
【问题讨论】:
标签: c linux unix linux-kernel
您一定在Advanced Linux Programming 中阅读过此内容。我想说,这是错误的措辞,并打算与下一段进行比较,下一段是关于 Windows 命名管道的:
... Win32 允许命名管道上的多个读写器连接 无需交错数据...
但是根据Windows Dev Center:
命名管道是用于通信的命名单向或双工管道 在管道服务器和一个或多个管道客户端之间。所有实例 命名管道共享相同的管道名称,但每个实例都有自己的 缓冲区和句柄,并为客户端/服务器提供单独的管道 沟通。实例的使用使多个管道客户端能够 同时使用相同的命名管道。
因此,实际上涉及多个管道连接(实例),在我看来,将它们与单个 Unix 管道进行比较没有多大意义。
尽管如此,The Open Group Base Specifications 说:
对管道或 FIFO 的写请求的处理方式与 常规文件,但以下例外: ... {PIPE_BUF} 字节或更少的写请求不得交错 来自其他进程的数据在同一管道上进行写入。写 大于 {PIPE_BUF} 字节的数据可能会交错,on 任意边界,由其他进程写入,无论是否 设置了文件状态标志的 O_NONBLOCK 标志。
因此,只要要写入的字节数不大于 PIPE_BUF,对 Linux (POSIX) 管道的单个 write 请求的数据块就不会被另一个写入器请求的数据交错(中断)。
【讨论】:
如果进程 A 在尝试写入 PIPE_BUF(或更少)字节的同时尝试写入 PIPE_BUF(或更少)字节,则可以保证写入是原子的,并且每个块都将保持完整(尽管它们的写入顺序是未指定的。)但是如果进程 A 写入的字节数超过 PIPE_BUF 字节,则来自进程 B 的数据可能会出现在与来自进程 A 的数据交错的管道中,并且操作系统不提供任何保证来防止数据从被交错。如果您想确保来自进程 A 的所有数据保持连续,则这些进程必须与其他一些机制同步。
【讨论】:
假设您有两个写入器 A 和 B,它们尝试同时写入一个数据块,最终进入管道的数据可能类似于 ABAAAABBAABB。
【讨论】: