管道读取不大于PIPE_BUF原子?

Modified on: Sat, 30 Jun 2018 08:45:00 +0800

GNU C库手册简要提到管道的读写都是原子

  

如果写入的数据大小不大于PIPE_BUF,则读取或写入管道数据是原子的。

然而,Linux上的手册页,如man 7 pipe,不提到读取是原子的,并且man 2 read明确指出read可能返回少于如果读取被信号中断,请求的金额。

对于在PIPE_BUF下读取长度的管道的读取调用在Linux上是否真的是原子的?

特别是,如果管道的单个写入器总是写入,例如,12字节块,并且有2个并发读取器用于读取12字节管道的管道,那么这些读取器是否正好读取12字节或者错误如EAGAIN,不可能获得部分读取?

此外,当写入器通过12字节块写入但并发读取器尝试一次读取PIPE_BUF/12块时,情况又如何呢?成功读取总是返回12个字节的确切乘数,还是可以返回任意数量的字节?

最佳答案

查看源代码,pipe_readsource/fs/pipe.c的实现在Linux内核中发生了很大变化,但是从快速阅读2.0.402.4.372.6.323.114.9,在我看来,每当有(或是,同时) read正在阻止)写入大小 w 和读取大小 r r > w 然后read将至少返回 w 字节。因此,如果您有固定大小的块(大小小于PIPE_BUF)并且始终读取相同大小的内容,那么您实际上可以保证始终读取整个块。

另一方面,如果你有可变大小的块,那么你没有这样的保证。只有写入端才能保证原子性:写入小于PIPE_BUF不会被另一个写入者删除。但是在读者方面,如果有例如写入10个字节,然后写入20个字节,稍后您尝试读取15个字节,然后您将获得完整的第一次写入和第二次写入的前5个字节。 read调用不会停止读取数据,直到它必须阻塞或其输出缓冲区已满。

如果要以块的形式传输数据,请使用数据报套接字而不是管道


相关问答

添加新评论