对并发写入命名管道的保证是什么?


32

例如,我创建了一个命名管道,如下所示:

mknod myPipe p

我从某些过程(例如某些服务器)中读取了该消息。出于示例目的,我使用tail:

tail -f myPipe

如果多个客户端进程向其中写入了一些消息(例如echo "msg" >> myPipe,,则很有可能消息被交错,如下所示:

 <beginning of message1><message2><ending of message1>

还是写入命名管道的过程是原子的?

Answers:


29

这取决于每个进程要写多少(假设您的操作系统在这方面符合POSIX)。来自write()

除了以下例外,对管道或FIFO的写入请求应以与常规文件相同的方式处理:
[...]

  • {PIPE_BUF}字节或更少字节的写请求不应与来自在同一管道上进行写操作的其他进程的数据交织。大于{PIPE_BUF}个字节的写操作可能会在任意边界与其他进程的写操作交错插入数据,无论是否设置了文件状态标志的O_NONBLOCK标志。

同样在关于管道和FIFO 的基本原理部分中

  • 原子/非原子:如果一个操作中写入的总量未与任何其他进程的数据交错,则写入是原子的。当有多个作者将数据发送到单个读者时,此功能很有用。应用程序需要知道可以自动执行多大的写请求。此最大值称为{PIPE_BUF}。POSIX.1-2008的这一卷并未说明对{PIPE_BUF}个字节的写请求是否是原子的,而是要求对{PIPE_BUF}个字节或更少的字节的写请求是原子的。

if的值PIPE_BUF由每个实现定义,但最小值为512字节(请参阅参考资料limits.h)。在Linux上,它是4096个字节(请参阅参考资料pipe(7))。


5
顺便说一句,PIPE_BUF至少保证为512。请注意,您还必须确保您的进程实际上在单个写入调用中将每一行写入其中。启用行缓冲(setvbuf(stdout, NULL, _IOLBF,512))可以做到这一点,而无需使用低级函数。
Random832 2013年

这是PIPE_BUF常见的Unix系统上观察值的表:ar.to/notes/posix#pipe-buf
Arto Bendiken 2014年

我不明白套接字如何复用...但是命名管道不可以?Unix上的所有内容都只是文件吗?lulz
Alexander Mills

@AlexanderMills:我不理解您的评论
Mat

1
@AlexanderMills:不,这是最小值
Mat Mat
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.