C++ 进程间并发文件写入

C++ 进程间并发文件写入,c++,.net,synchronization,c++-cli,mutex,C++,.net,Synchronization,C++ Cli,Mutex,我需要将来自不同进程的日志数据写入单个文件 我使用的是需要公共语言运行时支持的Windows互斥 Mutex^ m = gcnew Mutex( false,"MyMutex" ); m->WaitOne(); //... File Open and Write .. m->ReleaseMutex() P>我真的需要从C++到C++的CLI同步吗? 如果不使用原子,就可以了。但是我需要知道,与本地互斥体相比,使用此互斥体是否会降低性能。实际上,您根本不需要使用单独的互斥体,只需

我需要将来自不同进程的日志数据写入单个文件

我使用的是需要公共语言运行时支持的Windows互斥

Mutex^ m = gcnew Mutex( false,"MyMutex" );
m->WaitOne();
//... File Open and Write ..
m->ReleaseMutex()
<> P>我真的需要从C++到C++的CLI同步吗?
如果不使用原子,就可以了。但是我需要知道,与本地互斥体相比,使用此互斥体是否会降低性能。

实际上,您根本不需要使用单独的互斥体,只需使用文件本身即可。当使用CreateFile API调用打开文件时(请参阅),该调用使用名为dwShareMode的参数,该参数指定其他进程允许的并发访问。值0将阻止其他进程完全打开该文件

几乎所有的API都可以在引擎盖下打开文件映射到CreateFile,因此当您已经打开一个文件进行编写时,clr可能为您做了正确的事情

在C运行时中还有fsopen,它允许您打开带有共享标志的文件


我建议您测试从C#打开文件时的默认共享模式。如果默认情况下不阻止同时打开以进行写入,请使用fsopenfromc(或者可能有一个合适的C#函数)

>将CLR支持添加到C++应用程序中,只是为了获得互斥类的过多。有几个选项可用于在两个应用程序之间同步文件访问

选项1:互斥 如果您需要从多个进程写入文件,那么使用互斥是一种很好的方法。在Win32 API中使用。(无论如何,.Net互斥类只是这些函数的包装。)

正如另一个答案所指出的,您需要通过共享打开该文件,以便两个应用程序可以同时打开它。但是,这本身可能还不够:如果两个应用程序都试图写入文件的同一区域,那么您仍然需要确保一次只写入一个应用程序。想象一下,如果两个应用程序都查看文件的大小,那么两个应用程序都试图同时写入该字节偏移量:即使两个应用程序都试图附加到文件的末尾,但最终都会相互碰撞

选项2:仅作为附加打开 如果您纯粹是在文件末尾进行写入,并且从未尝试读取任何内容或在文件末尾以外的任何位置进行写入,那么您可以使用一种特殊模式,该模式允许您不使用互斥。如果打开文件时
dwDesiredAccess
设置为
file\u APPEND\u DATA | SYNCHRONIZE
,而没有其他内容(不包括
file\u WRITE\u DATA
),则操作系统将负责确保最后写入文件的所有数据,而且两个写入数据的应用程序不会相互覆盖。此行为记录在:

如果只设置了FILE_APPEND_DATA和SYNCHRONIZE标志,则调用者只能写入文件的末尾,并且忽略有关写入文件的任何偏移量信息。但是,对于这种类型的写入操作,文件将根据需要自动扩展

选项3:锁定文件
另一种方法是使用
LockFile
方法。使用(或),您可以让两个应用程序打开文件,并让每个应用程序锁定其要写入的文件部分。这比互斥体提供了更多的粒度,允许同时进行非重叠写入。(在整个文件上使用
LockFile
将提供与互斥体相同的基本效果,另外还有一个好处,即它将防止其他应用程序在您编写文件时写入该文件。)有一个很好的例子说明了如何在上使用
LockFile

我很清楚你在问什么:是否有一个没有/clr的不同解决方案(是的,很多),或者如果这样一个不同的解决方案明显更快(可能没有),或者其他什么……问题是一个“包含”,你没有显示,糟糕的片段。具有非托管线程原语定义(如std::thread、std::mutex等)的.h文件严格执行一条规则,即托管程序不能假定托管线程保证在非托管操作系统线程上运行。这在实践中从未发生过,但在技术上是可行的。您不能包含此类文件,如有必要,请使用pimpl将其保存在您自己的.h文件之外。使用Windows互斥体可以简化工作。。所以我想选择它。如果这不是一个好方法,那么对于从不同进程并发写入文件,我还能做些什么呢?使用Boost::mutex怎么样?
HANDLE mutex = CreateMutex(NULL, false, "MyMutex");

DWORD waitResult = WaitForSingleObject(mutex, INFINITE);
if (waitResult == WAIT_OBJECT_0)
{
    // TODO: Write the file
    WriteFile(...);

    ReleaseMutex(mutex);
}