把两段文字先后送入Linux管道,读取一侧看到的首先是一条字节流,而不是已经附好两个消息标签的队列。Linux man-pages的pipe(7)明确写道,管道提供的通信通道没有消息边界。[1] 这句话关系到怎样阅读进程通信的说明:写入端认为自己发送了几条业务消息,并没有由管道自动变成读取端的消息分组。
手册先定义两端关系。管道和FIFO提供单向进程间通信通道,各有读端与写端,写端送入的数据可以从读端取得。这里的方向来自通道定义,不能把同一个管道的两端画成一对天然双向的接口。本文只说明Linux手册的对象,没有创建通信通道或运行任何程序。
FIFO另外具有文件系统中的名称。手册将管道与FIFO的区别放在创建和打开方式上,并说明完成这些动作之后,两者具有相同的I/O语义。因此,有名字与没有这里所述名称,不应被继续推成两套不同的消息划分规则;FIFO并没有因名字出现就获得本节未规定的消息边界。
可以作一个纯概念的例子:发送方把业务资料称为“通知甲”和“通知乙”。在管道这一层,来源能够支持的描述仍是先后进入通道的字节。两条通知怎样在业务层被识别,需要另外的约定,不能仅从发送方用了两个名称就认定管道已保存两个业务单元。这是从无消息边界作出的资料分析,不是一次真实读写或读取长度测试。
还要区分暂时没有数据与结束。手册说明,在阻塞模式下,读取空管道会等待可用数据。它又将EOF联系到所有指向写端的文件描述符都已关闭,读取结束时返回零。对于数据已经读尽的情境,“现在没有内容”和“写入端的所有引用已结束”不是同一项条件。单个写端引用关闭,也不能被改写成所有写端都已关闭。
这种区分有助于读懂通信过程图。图中可以分别标注数据是否可读、写端是否仍有打开的引用,而不是只用“空”字同时代表等待与结束。也不能把关闭写端说成清空已经写入的数据;本篇并未测试任何缓冲区内容或安排关闭操作。
手册还说明不能对管道使用lseek。这里的顺序读取对象,与可按位置寻址的文件说明需要分开理解。本文采用Linux man-pages 6.19中DESCRIPTION及必要邻接,条目日期和HTML生成日期不作首发日;不采用容量配置、信号处置或进程关闭步骤,也不推广到所有平台的管道实现。
信息来源
本文基于上述公开资料整理,未使用来源页面的图片、视频或嵌入媒体。