如何从两个进程同步 - 在一个文件上进行原子写入?

时间:2011-08-01 08:42:40

标签: c atomic

我有两个进程,每个进程写入大量数据缓冲区,我想控制将这些进程的写入同步到一个文件。

处理1写入包括(A1,A2,A3)的缓冲器A和包括(B1,B2,B3)的处理2写入缓冲器B.当我们使用write()系统调用将这些缓冲区写入磁盘到同一个文件时(整个缓冲区一次:write(fd, A, sizeof(A))),文件架构如何?

  • 是这样的:A,B或B,A可能吗?
  • 或者它可能是这样的:A1,A2,B1,A3,......

我问这个是因为系统调用是原子的。如果我们写的数据缓冲区太大会发生什么。它是否像常规磁盘文件的管道一样?

3 个答案:

答案 0 :(得分:4)

如果要存在两个缓冲区的内容,则必须打开设置了O_APPEND标志的文件。 append标志在写入之前寻找文件的末尾。如果没有这个设置,两个进程可能都指向文件的相同或重叠区域,而最后写入的任何一个将覆盖另一个进程写入的内容。

每次调用write都会写入所请求的字节数。如果您的进程被信号中断,那么您最终可以进行部分写入 - 返回写入的实际字节数。无论你是否写入了所有的字节,你都会编写一个连续的文件部分。你没有得到你提到的交错效果作为你的第二种可能性(例如A1,B1,A2,B2,......)。

如果您只是部分写作,那么您的行动将取决于您。您可以继续写入(从缓冲区开始偏移先前写入的字节数),也可以放弃写入的其余部分。只有这样才能获得交错效果。

如果在另一个进程写入之前让一个写入的内容完成很重要,那么在尝试写入任何数据之前,您应该考虑锁定该文件以进行独占写入访问(两个进程都必须检查)。 / p>

答案 1 :(得分:2)

假设缓冲区的大小相同,结果将是A或B,具体取决于最后安排的进程。

写入系统调用是原子的,是的,这意味着结果将是A或B,而不是两者的混合。

假设您希望文件中同时包含A和B,则可以使用O_APPEND打开文件;请注意,这不适用于NFS。

另一个选择是每个进程跟踪它应该使用哪个文件偏移量,并使用lseek()或pwrite()

答案 2 :(得分:2)

对于访问该文件的程序,您肯定需要某种形式的同步,否则最终会出现混乱的文件内容。 write系统调用可以写入比您请求的更少的字节,因此您的块A1,A2或B1,B2可能只是部分写入。这可能经常发生,或很少发生,具体取决于许多条件。如果它只在一周内发生一次,那么你将会有一个很难检测到的错误。

作为解决方案,您可以使用文件锁定(man 2 flockman fcntl并搜索锁定)。另一种可能性是使用信号量(man -k semaphore)来同步您的程序写入或其他形式的IPC。