c ++多个进程写入同一个文件 - 进程间互斥锁?

c++ multiple processes writing to the same file - Interprocess mutex?

我的问题是:从多个进程写入文件的最佳方式(或至少是有效方式)是什么?

注意:我正在使用 c++11,我希望它在任何平台上 运行(即仅纯 c++ 代码)。

我做了一些研究,这是我得出的结论:

  1. 在我的进程中,我有多个线程。这很容易在每个进程中使用互斥锁来序列化对文件的访问来处理。
  2. 不能使用 c++/c++11 互斥锁或条件变量在进程之间进行序列化。
  3. 我需要某种外部信号量/锁定文件来充当 "mutex"...但我不确定该怎么做。

我见过应用程序在使用时使用诸如创建“.lock”文件之类的东西。但是对于多个快速访问,这似乎不起作用(即在一个进程确定文件不存在后,另一个进程可以创建它,然后第一个进程也将尝试创建它)因为测试和创建文件的操作是不是原子的。

注意:每个进程总是一次写入一整行。我原以为这可能足以进行操作 "atomic" (因为整行会在下一行之前得到缓冲),但情况似乎并非如此(除非我的代码有误)因为我(很少)得到一条损坏的线。这是我如何进行写入的代码片段(如果相关):

// in c'tor
m_osFile.open("test.txt", std::fstream::out | std::fstream::app)

// in write func (std::string data)
osFile << data<< std::endl;

这一定是一个普遍的问题,但我还没有找到可行的解决方案。欢迎任何代码片段。

通常操作系统会提供特殊的函数来锁定保证原子性的文件(如lockf on Linux or LockFile(Ex) on Windows). As by now, the C++ standard library provides no such functionality, so a plattform-independent approach to such facilities is provided by e.g. Boost.Interprocess.

好吧,我可以想象两种情况。由于您没有在问题中指定进程是如何产生的,我想有两种情况:

  1. 您的第一个进程产生第二个进程(例如使用 fork())。
  2. 这两个进程在您的环境中分别生成。

在第一种情况下,进程之间对所需资源(互斥量)的简单互斥访问应该可以正常工作。这将阻止一个进程访问另一个进程正在使用的资源。

第二种情况有点复杂,它需要每个进程都承认另一个进程的存在。已经讨论过类似的问题 here, where it's present an interesting link on how to avoid race conditions。为此,我还会考虑检查 O_EXCLO_CREAT 标志

My question is this: what is the best way (or at least an effective way) to write to a file from multiple processes?

最好的方法是...不要这样做!

这真的像是一种日志(追加)。我会让每个进程编写自己的文件,然后在需要时合并它们。这至少是通用的方法,这里是基本原理。

任何类型的 intra-process 锁定都不起作用。打开的文件在 OS 级别有缓冲,即使在某些 OSes (windows) 上关闭后也是如此。

如果您想要一个可移植的解决方案 ("I want this to run on any platform"),您将无法执行文件锁定:根据所使用的文件系统(例如:samba、 NFS).

并发且可靠地写入单个文件实际上是 system-dependent activity,今天。

我并不是说这不可能 - 数据库引擎和其他应用程序可以可靠地执行此操作,但这是一个自定义操作。

作为一个很好的替代方案,您可以让一个进程充当收集器(如 Gem Taylor 所提议),所有其他进程充当生产者,但这不是一个可靠的替代方案:日志需要to get to disk "simply": 如果一个bug可以让日志不被写入,那么日志的目的就会丢失。

然而,您可以考虑使用这种方法,将进程解耦并让它们之间的消息可靠高效地交换:如果是这种情况,您可以考虑使用像 RabbitMQ 这样的消息传递解决方案。

在这种情况下,所有进程都将它们的 "lines" 发布到消息代理,并且另一个进程使用这些消息并将它们写入文件。

您可以在所有进程之间的共享内存中声明您的文件描述符和与之关联的互斥锁(条件?)。