xud*_*fsd 11 c linux posix systems-programming
posix标准指定当写入少于PIPE_BUF字节到管道或FIFO被授予原子时,也就是说,我们的写入不会与其他进程混合.但是我没有找到关于常规文件的标准规范.我的意思是,当我们写的少于PIPE_BUF时,它也会被授予原子性.但我想知道常规文件有这样的限制吗?我的意思是,管道有容量,所以当写入管道并超出其容量时,内核会让编写器进入休眠状态,因此其他进程将有机会写入,但是常规文件似乎没有这样的限制,我是对的?
我正在做的是几个进程生成一个文件的日志.当然,设置O_APPEND.
引用自http://pubs.opengroup.org/onlinepubs/9699919799/toc.htm(单一 UNIX 规范,第 4 版,2010 版):
POSIX.1-2008 的这一卷没有指定从多个进程并发写入文件的行为。应用程序应该使用某种形式的并发控制。
该规范确实解决了在多个读者的情况下关于写的写语义是如何发生的,但是正如您从上面看到的那样,规范没有定义多个并发写者的行为。
上面的注释是关于files 的。对于管道和 FIFO, PIPE_MAX 语义适用,并发写入保证不可分割达 PIPE_MAX 字节。
对管道或 FIFO 的写请求应以与常规文件相同的方式处理,但有以下例外:
{PIPE_BUF} 字节或更少字节的写入请求不应与在同一管道上进行写入的其他进程的数据交错。无论是否设置了文件状态标志的 O_NONBLOCK 标志,大于 {PIPE_BUF} 字节的写入可能会在任意边界上将数据与其他进程的写入交错。
对于真实的文件系统,情况很复杂。一些本地文件系统可能会通过在写入期间锁定文件句柄来强制将原子写入任意大小(内存限制),有些可能不会(我试图查看 ext4 逻辑,但在http://lxr.linux.no附近的某个地方丢失了跟踪/linux+v3.5.3/fs/jbd2/transaction.c#L147)。
对于非本地文件系统,结果或多或少是可取的。只是不要在没有某种形式的显式锁定的情况下尝试在网络文件系统上进行并发写入(或者您绝对肯定您正在使用的网络文件系统的语义)。
顺便说一句, O_APPEND 保证不同进程的所有写入都到达文件的末尾。然而,正如上面 SUS 所指出的,如果写入确实是并发的(同时发生),则行为是未定义的。在早期的单进程和非抢占式 UNIX 上,这并不重要,因为在其他人有机会编写之前完成了对 write(2) 的调用......
对于操作系统(Linux?)和文件系统(ext4?)的特定组合,可以肯定地回答这个问题。一般的答案?正如 SUS 所说——“未定义的行为”。
一个文件的多个写入者可能会混淆事情。但是使用 O_APPEND 打开的文件会在每次写访问时自动追加。
如果您想保留 C stdio 接口而不是较低级别的接口,请使用“a”或“a+”(映射到 O_APPEND)打开文件,设置一个足够大的缓冲区,以便无需在您的文件中写入记录并在构建完成后使用 fsync 强制写入。我不确定 POSIX 是否保证它(C 对此只字未提)。