在linux中的进程之间写入(2)/读取(2)primefaces性

我有一个情况,有两个进程在同一个文件上起作用,一个是作者,一个是读者。 该文件是一行文本文件,写入程序将该行重新写入一个循环中。 读者阅读该行。 伪代码如下所示:

作家过程

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] } 

经过一段时间运行这两个进程,我可以看到readbufxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyxx

我的理解是写入对于512字节的大小是primefaces的。 但从我的实验来看,它看起来像primefaces只有16个字节。

手册页没有提到任何关于普通文件的primefaces性的内容,它只提到512字节的pipe道primefaces性。

我已经用tmpfs和ext4试过了,结果是一样的。 与O_SYNC ,ext4写入成为primefaces,我的理解是因为写入不会返回,直到它碰到磁盘,但O_SYNC不会帮助tmpfs( /dev/shm )。

除了管道上的写入(其中写入最多PIPE_BUF (≥512)字节保证为原子性,但读取没有原子性保证),POSIX不给予write原子操作的最低保证。 readwrite的操作以字节值来描述; 除了管道之外,与围绕单字节write操作的循环相比, write操作不提供额外的保证。

我并不知道Linux会提供什么额外的保证,既不是16也不是512.在实践中,我期望它取决于内核版本,文件系统,还有其他因素,比如底层的块设备, CPU数量,CPU架构等

O_SYNCO_RSYNCO_DSYNC保证( 同步I / O数据完整性 ,在readwrite POSIX的可选SIO功能时给出的)不是你所需要的。 它们保证写操作在readwrite系统调用之前被提交到永久存储器,但不要求在read操作正在进行时启动的read操作。

在您的情况下,读取和写入文件看起来不是正确的工具集。

  • 如果您只需传输少量数据,请使用管道。 不要太担心复制:在大多数处理或上下文切换的范围内,复制内存中的数据非常快。 另外Linux在优化拷贝方面相当不错。
  • 如果您需要传输大量数据,则应该使用某种形式的内存映射:如果不需要磁盘备份,则使用共享内存段,如果是,则使用mmap 。 这不会神奇地解决原子性问题,但可能会提高适当的同步机制的性能。 要执行同步,有两个基本的方法:
    • 生产者将数据写入共享内存,然后向消费者发送一个通知,指明可用的数据。 消费者只能根据请求处理数据。 通知可能使用相同的通道(例如mmap + msync )或不同的通道(例如管道)。
    • 生产者将数据写入共享内存,然后刷新写入(例如msync )。 然后生产者将一个已知的值写入一个机器字(一个sig_atomic_t通常会起作用,尽管它的原子性只能在信号上得到保证 – 或者实际上是一个uintptr_t )。 消费者读取一个机器字,并只处理相应的数据,如果这个字有一个可接受的价值。