我有一个情况,有两个进程在同一个文件上起作用,一个是作者,一个是读者。 该文件是一行文本文件,写入程序将该行重新写入一个循环中。 读者阅读该行。 伪代码如下所示:
作家过程
char buf[][18] = { "xxxxxxxxxxxxxxxx", "yyyyyyyyyyyyyyyy" }; i = 0; while (1) { pwrite(fd, buf[i], 18, 0); i = (i + 1) % 2; }
阅读器进程
while(1) { pread(fd, readbuf, 18, 0); //check if readbuf is either buf[0] or buf[1] }
经过一段时间运行这两个进程,我可以看到readbuf
是xxxxxxxxxxxxxxxxyy
或yyyyyyyyyyyyyyyyxx
。
我的理解是写入对于512字节的大小是primefaces的。 但从我的实验来看,它看起来像primefaces只有16个字节。
手册页没有提到任何关于普通文件的primefaces性的内容,它只提到512字节的pipe道primefaces性。
我已经用tmpfs和ext4试过了,结果是一样的。 与O_SYNC
,ext4写入成为primefaces,我的理解是因为写入不会返回,直到它碰到磁盘,但O_SYNC
不会帮助tmpfs( /dev/shm
)。
除了管道上的写入(其中写入最多PIPE_BUF
(≥512)字节保证为原子性,但读取没有原子性保证),POSIX不给予write
原子操作的最低保证。 read
和write
的操作以字节值来描述; 除了管道之外,与围绕单字节write
操作的循环相比, write
操作不提供额外的保证。
我并不知道Linux会提供什么额外的保证,既不是16也不是512.在实践中,我期望它取决于内核版本,文件系统,还有其他因素,比如底层的块设备, CPU数量,CPU架构等
O_SYNC
, O_RSYNC
和O_DSYNC
保证( 同步I / O数据完整性 ,在read
和write
POSIX的可选SIO功能时给出的)不是你所需要的。 它们保证写操作在read
或write
系统调用之前被提交到永久存储器,但不要求在read
操作正在进行时启动的read
操作。
在您的情况下,读取和写入文件看起来不是正确的工具集。
mmap
。 这不会神奇地解决原子性问题,但可能会提高适当的同步机制的性能。 要执行同步,有两个基本的方法:
mmap
+ msync
)或不同的通道(例如管道)。 msync
)。 然后生产者将一个已知的值写入一个机器字(一个sig_atomic_t
通常会起作用,尽管它的原子性只能在信号上得到保证 – 或者实际上是一个uintptr_t
)。 消费者读取一个机器字,并只处理相应的数据,如果这个字有一个可接受的价值。