可以安全地让多个进程同时写入同一个文件吗? [CentOs 6,ext4]

时间:2011-10-20 21:30:55

标签: filesystems multiprocessing seek

我正在构建一个系统,其中多个从属进程通过unix域套接字进行通信,并且它们同时写入相同文件。我从未研究过文件系统或这个特定的文件系统(ext4),但感觉这里可能存在一些危险。

每个进程写入输出文件的不相交子集(即,正在写入的块中没有重叠)。例如,P1仅写入文件的前50%,而P2仅写入第二个50%。或者P1可能仅写入奇数编号的块,而P2写入偶数编号的块。

使用P1P2(在不同的线程上同时运行)写入同一文件而不使用任何锁定是否安全?换句话说,文件系统是否隐式强加某种锁定?

注意:我很遗憾无法输出多个文件并在以后加入。

注意:自发布此问题以来,我的阅读内容与下面仅发布的答案不符。我读过的所有内容都表明我想做的事情很好,而下面的受访者坚持我所做的是不安全的,但我无法辨别所描述的危险。

2 个答案:

答案 0 :(得分:26)

如果您正在使用POSIX“原始”IO系统调用,例如read(),write(),lseek()等,那么您所做的事情似乎完全没问题。

如果您使用C stdio(fread(),fwrite()和朋友)或其他具有自己的用户空间缓冲的语言运行时库,则“Tilo”的答案是相关的,因为缓冲,在某种程度上,你的控制之外,不同的进程可能会覆盖彼此的数据。

Wrt OS锁定,而POSIX声明写入或读取小于PIPE_BUF的大小对某些特殊文件(管道和FIFO)来说是原子的,对常规文件没有这样的保证。在实践中,我认为页面中的IO很可能是原子的,但是没有这样的保证。操作系统仅在内部锁定到保护其自身内部数据结构所必需的程度。可以使用文件锁或其他一些进程间通信机制来序列化对文件的访问。但是,所有这些只与您有几个进程在文件的同一区域执行IO有关。在你的情况下,当你的进程正在执行IO来分离文件的各个部分时,这些都不重要,你应该没事。

答案 1 :(得分:24)

不,通常这样做是不安全的!

您需要为每个进程获取一个独占的写锁定 - 这意味着所有其他进程必须等待一个进程写入文件...您拥有的I / O密集型进程越多,等待时间。

最好每个进程有一个输出文件,并在行的开头格式化带有时间戳和进程标识符的文件,以便以后可以脱机合并和排序这些输出文件。

提示:检查Web服务器日志文件的文件格式 - 这些是使用行开头的时间戳完成的,因此可以稍后对它们进行组合和排序。


修改

UNIX进程在打开文件(例如4096字节)时使用某个/固定的缓冲区大小,以便与磁盘上的文件进行数据传输。写入缓冲区已满后,进程将其刷新到磁盘 - 这意味着:它将完整的完整缓冲区写入磁盘!请注意,缓冲区已满时会发生这种情况! - 当有一个终点时!这意味着即使对于将面向行的文本数据写入文件的单个进程,这些行通常在刷新缓冲区时在中间某处切割。只有在最后,当文件在写入后关闭时,你能否认为该文件包含完整的行!

因此,根据您的进程何时决定刷新缓冲区,它们会在不同时间写入文件 - 例如顺序不确定/可预测当缓冲区刷新到文件时,您可以不要假设它只会写完整行 - 例如它通常会写出部分行,如果多个进程在没有同步的情况下刷新缓冲区,则会搞乱输出。

在维基百科上查看这篇文章:http://en.wikipedia.org/wiki/File_locking#File_locking_in_UNIX

<强>引用:

  

Unix操作系统(包括Linux和Apple的Mac OS X,   有时称为Darwin)通常不会自动锁定打开的文件   或运行程序。有几种文件锁定机制   提供不同版本的Unix和许多操作系统   支持多种兼容性。两个最常见的   机制是fcntl(2)和flock(2)。第三种这样的机制是   lockf(3),它可以是单独的,也可以用任何一个来实现   前两个原语。

您应该使用 flock或Mutexes 来同步进程,并确保其中只有一个可以一次写入该文件。

正如我前面提到的,为每个进程提供一个输出文件可能更快,更简单,更直接,然后在需要时(离线)组合这些文件。这种方法是例如,某些Web服务器使用它需要从多个线程登录到多个文件 - 并且需要确保不同的线程都是高性能的(例如,不必在文件锁上等待彼此)。


以下是相关帖子:(查看Mark Byer的答案!接受的答案不正确/相关。)

Is it safe to pipe the output of several parallel processes to one file using >>?


编辑2:

在评论中,您说要将不同进程的固定大小二进制数据块写入同一文件。

只有在您的块大小与系统文件缓冲区大小完全相同的情况下才能正常工作!

确保固定块长度与系统的文件缓冲区大小完全相同。否则,您将遇到与未完成的行相同的情况。例如如果您使用16k块,并且系统使用4k块,那么通常您将看到文件中的4k块看似随机顺序 - 无法保证您将始终在同一进程中连续看到4个块