管道的原子性 linux写操作原子性

Posted qiumingcheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了管道的原子性 linux写操作原子性相关的知识,希望对你有一定的参考价值。

从本质上说,管道也是一种文件,但他又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题

限制管道的大小。实际上,管道是一个固定大小的缓冲区。在Linux中该换冲区的大小为一页,4k

使得他的大小不像文件那样不加检验的增长。使用固定缓冲区也会带来问题,比如再写管道时可能变满

当这种情况发生时,随后对管道的write()调用被阻塞,等待某些数据被读取,以便腾出足够的空间供

write()调用。

读取工作也可能比写的进程快。当所有进程的数据被读取完时,一个随后的read()调用将默认的被阻塞、

管道变空。这种情况发生时,一个随后的read()调用将被默认的阻塞,等待某些数据被写入,这样就解决了read()

调用将被默认的阻塞,等待某些数据将被写入,这解决了read()调用返回文件结束的问题。

一个管道的容量是有限的。POSIX规定,少于 PIPE_BUF 的写操作必须原子完成:要写的数据应被连续的写到管道;大于 PIPE_BUF 的写操作可能是非原子的: 内核可能会把此数据与其它进程的对此管道的写操作交替起来。POSIX规定PIPE_BUF至少为512B(linux中为4096B),具体的语义如下: 其中n为要写的字节数
    n <= PIPE_BUF, O_NONBLOCK无效:原子的写入n个字节。如果管道当前的剩余空间不足以立即写入n个字节,就阻塞直到有足够的空间。
    n <= PIPE_BUF, O_NONBLOCK有效:写入具有原子性,如果有足够的空间写入n个字节,write立即成功返回。否则一个都不写入,返回错误,并设置errno为EAGAIN。
    n >  PIPE_BUF, O_NONBLOCK无效:非原子写。可能会和其它的写进程交替写。write阻塞直到将n个字节写入管道。
    n >  PIPE_BUF, O_NONBLOCK有效:如果管道满,则write失败,返回错误,并将errno设置为 EAGIN。如果不满,则返回写入的字节数为1~n,即部分写入,写入时可能有其他进程穿插写入。

结论:
1、当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
2、当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。

以上是关于管道的原子性 linux写操作原子性的主要内容,如果未能解决你的问题,请参考以下文章

[linux] page 写磁盘并不是原子性

自己动手写把”锁”---原子性操作

MongoDB中写操作的原子性是啥意思?

Java 并发编程线程操作原子性问题 ( 问题业务场景分析 | 使用 synchronized 解决线程原子性问题 )

volatile关键字原子性和可见性

什么是程序的原子性