fre*_*eit 60
一个大小为'PIPE_BUF'的写入应该是原子的.这至少应该是512字节,虽然它可能很容易变大(linux似乎将它设置为4096).
这假设您正在谈论所有完全符合POSIX的组件.例如,在NFS上不是这样.
但假设您写入以"O_APPEND"模式打开的日志文件并将您的行(包括换行符)保留在"PIPE_BUF"字节长的情况下,您应该能够将多个写入程序写入日志文件而不会出现任何损坏问题.任何中断都将在写入之前或之后到达,而不是在中间.如果您希望文件完整性在重新启动后继续存在,您还需要fsync(2)在每次写入后调用,但这对于性能而言非常糟糕.
澄清:阅读评论和Oz Solomon的回答.我不确定O_APPEND应该具有那么PIPE_BUF大小的原子性.它完全有可能是Linux实现的方式write(),或者可能是由于底层文件系统的块大小.
Nia*_*las 32
编辑: 2017年8月更新,包含最新的Windows结果.
作为提议的Boost.AFIO的作者,我将给出一个测试代码和结果链接的答案,它实现了异步文件系统和文件i/o C++库.
首先,Windows上的O_APPEND或等效的FILE_APPEND_DATA意味着最大文件范围(文件"长度")的增量在并发编写器下是原子的.这是由POSIX保证的,Linux,FreeBSD,OS X和Windows都正确实现了它.Samba也正确地实现了它,v5之前的NFS没有,因为它缺乏以原子方式追加的有线格式功能.因此,如果您使用仅附加文件打开文件,则除非涉及NFS,否则并发写入不会在任何主要操作系统上相互撕裂.
然而,对原子附加的并发读取可能会看到根据操作系统,文件系统以及您打开文件的标志而破坏写入 - 最大文件范围的增量是原子的,但写入相对于读取的可见性可能会也可能不会是原子的.以下是标志,操作系统和文件系统的快速摘要:
带有NTFS的Microsoft Windows 10:更新原子性= 1字节,直到并包括10.0.10240,从10.0.14393至少1Mb,可能是无限(*).
Linux 4.2.6 with ext4:update atomicity = 1 byte
FreeBSD 10.2 with ZFS:update atomicity =至少1Mb,可能是无限的(*)
带有NTFS的Microsoft Windows 10:仅当页面对齐时,更新原子性=直到并包括10.0.10240最多4096字节,否则如果FILE_FLAG_WRITE_THROUGH关闭则为512字节,否则为64字节.请注意,这个原子性可能是PCIe DMA的一个特性而不是设计的.自10.0.14393起,至少1Mb,可能是无限的(*).
Linux 4.2.6 with ext4:update atomicity =至少1Mb,可能是无限(*).请注意,早期使用ext4的Linux肯定没有超过4096字节,XFS肯定用于自定义锁定,但看起来最近Linux已经解决了这个问题.
FreeBSD 10.2 with ZFS:update atomicity =至少1Mb,可能是无限的(*)
您可以在https://github.com/ned14/afio/tree/master/programs/fs-probe上查看原始实证测试结果.注意我们只测试512字节倍数的撕裂偏移,所以我不能说在读 - 修改 - 写周期中是否会撕裂512字节扇区的部分更新.
因此,为了回答OP的问题,O_APPEND写入不会相互干扰,但是并发读取O_APPEND写入可能会在Linux上使用ext4看到撕裂写入,除非O_DIRECT打开,因此您的O_APPEND写入需要是扇区大小倍数.
(*)"可能无限"源于POSIX规范中的这些子句:
当它们在常规文件或符号链接上运行时,以下所有函数在POSIX.1-2008中指定的效果中应该是原子的... [许多函数] ... read()... write( )...如果两个线程分别调用其中一个函数,则每个调用应该看到另一个调用的所有指定效果,或者没有一个.[资源]
和
写入可以相对于其他读取和写入进行序列化.如果在数据的write()之后可以证明(通过任何方式)文件数据的read(),它必须反映write(),即使调用是由不同的进程完成的.[资源]
但反过来说:
此卷POSIX.1-2008未指定从多个进程并发写入文件的行为.应用程序应使用某种形式的并发控制.[资源]
Oz *_*mon 26
我写了一个脚本来经验测试最大原子附加大小.用bash编写的脚本生成多个工作进程,这些进程都将特定于工作程序的签名写入同一文件.然后它读取文件,查找重叠或损坏的签名.您可以在此博客文章中查看脚本的来源.
实际的最大原子附加大小不仅因操作系统而异,而且因文件系统而异.
在Linux + ext3上,大小为4096,在Windows + NTFS上,大小为1024.有关更多大小,请参阅下面的注释.
Bas*_*ard 16
这是标准所说的内容:http://www.opengroup.org/onlinepubs/009695399/functions/pwrite.html.
如果
O_APPEND设置了文件状态标志的标志,则在每次写入之前将文件偏移设置为文件的末尾,并且在改变文件偏移和写入操作之间不应发生中间文件修改操作.