在UNIX中文件追加primefaces吗?

一般来说,当我们在UNIX中从多个进程追加到一个文件时,我们会认为什么是理所当然的? 是否有可能丢失数据(一个进程覆盖另一个进程的变化)? 数据是否可能被破坏? (例如,每个进程追加一行,每个追加到一个日志文件,是否有可能两条线被破坏?)如果在上述意义上,追加不是primefaces的,那么确保互斥的最好方法是什么?

大小为“PIPE_BUF”的写入应该是primefaces的。 这应该是至less512字节,虽然它可以很容易地更大(Linux似乎已经设置为4096)。

这假设你正在谈论所有完全符合POSIX标准的组件。 例如,在NFS上这不是真的。

但假设你写了一个以'O_APPEND'模式打开的日志文件,并且保持你的行(包括换行符)在'PIPE_BUF'字节之下,那么你应该可以有多个写入者到一个日志文件而没有任何损坏问题。 任何中断将在写入之前或之后到达,而不是在中间。 如果您希望文件完整性在重新启动后仍然存在,则每次写入后都需要调用fsync(2) ,但这对性能来说太糟糕了。

澄清 :阅读评论和Oz所罗门的答案 。 我不确定O_APPEND是否应该具有PIPE_BUF大小的primefaces性。 这完全有可能是Linux实现write() ,也可能是由于底层文件系统的块大小。

编辑: 2017年8月更新最新的Windows结果。

我将给出一个答案,提供testing代码和结果的链接,作为提出的Boost.AFIO的作者,它实现了一个asynchronous文件系统和文件I / O C ++库。

首先,O_APPEND或Windows上等效的FILE_APPEND_DATA表示最大文件范围(文件“length”)的增量在并发作者下是primefaces的 。 这是由POSIX保证的,Linux,FreeBSD,OS X和Windows都正确实施。 Samba也正确地实现了它,在v5之前的NFS并没有缺乏primefaces级连线的能力。 所以如果你用append-only来打开你的文件,除非涉及到NFS,否则在任何主要操作系统上并发写入都不会相互撕裂

然而,对primefaces追加的并发读取 可能会根据操作系统,文件系统以及您打开文件的哪些标志看到破坏写入 – 最大文件范围的增量是primefaces的,但是写入相对于读取的可见性可能会或可能不会是primefaces的。 这是一个标志,操作系统和文件系统的快速总结:


否O_DIRECT / FILE_FLAG_NO_BUFFERING:

带有NTFS的Microsoft Windows 10:更新primefaces性= 1个字节,直到包括10.0.10240,从10.0.14393起至less1Mb,可能是无限(*)。

Linux 4.2.6与ext4:更新primefaces性= 1个字节

具有ZFS的FreeBSD 10.2:更新primefaces性=至less1Mb,可能无限(*)

O_DIRECT / FILE_FLAG_NO_BUFFERING:

带有NTFS的Microsoft Windows 10:更新primefaces性直到和包括10.0.10240最多4096字节只有页alignment,否则512字节如果FILE_FLAG_WRITE_THROUGH关,否则64字节。 请注意,这个primefaces性可能是PCIe DMA的一个特性,而不是devise成的。从10.0.14393开始,至less1Mb,可能是无限的(*)。

Linux 4.2.6与ext4:更新primefaces性=至less1Mb,可能无限(*)。 请注意,较早的ext4的Linux用户肯定没有超过4096字节,XFS肯定有自定义的locking,但看起来像最近的Linux终于解决了这个问题。

具有ZFS的FreeBSD 10.2:更新primefaces性=至less1Mb,可能无限(*)


您可以在https://github.com/ned14/afio/tree/master/programs/fs-probe上查看原始的实证testing结果。; 注意我们只testing512字节倍数的破损偏移量,所以我不能说在读 – 修改 – 写周期中512字节扇区的部分更新是否会破裂。

因此,为了回答OP的问题,O_APPEND写入不会互相干扰,但是对于O_APPEND写入的并发读取可能会在Linux上使用ext4写入,除非O_DIRECT处于打开状态,因此您的O_APPEND写入需要是扇区大小的倍数。


(*)“可能无限”来源于POSIX规范中的这些条款:

下面的所有函数在POSIX.1-2008规定的效果中,当它们在常规文件或符号链接上运行时,它们应该相互primefaces化… [许多函数] … read()… write( )…如果两个线程分别调用其中一个函数,则每个调用都将看到另一个调用的所有指定的效果,或者都不是。 [资源]

写入可以被序列化为相对于其他读取和写入。 如果一个read()文件数据可以被certificate(通过任何方法)在write()之后发生,那么它必须反映write(),即使这个调用是由不同的进程完成的。 [资源]

但相反:

本卷的POSIX.1-2008没有指定从多个进程并发写入文件的行为。 应用程序应该使用某种forms的并发控制。 [资源]

你可以在这个答案中阅读更多关于这些的含义

我写了一个脚本来经验地testing最大primefaces追加大小。 用bash编写的脚本生成了多个工作进程,这些进程都将特定于工作人员的签名写入同一个文件。 然后它读取文件,寻找重叠或损坏的签名。 您可以在此博客文章中查看脚本的来源。

实际的最大primefaces附加大小不仅取决于操作系统,还取决于文件系统。

在Linux + ext3上,大小是4096,而在Windows + NTFS上,大小是1024.有关更多大小,请参阅下面的注释。

这是标准所说的: http : //www.opengroup.org/onlinepubs/009695399/functions/pwrite.html 。

如果设置了文件状态标志的O_APPEND标志,则在每次写入之前,文件偏移量应设置为文件末尾,在改变文件偏移量和写入操作之间不得进行中间文件修改操作。