从不同的进程可靠地写入相同的文件

我确实创build了一个很好的C ++ Tracing解决scheme。 在一个进程内一切都很好,但是当我从不同的进程打开输出文件时,数据得不到正确的写入。 我用FILE_SHARE_WRITE打开文件,以便能够在文件已经打开时写入文件。 然后,我确实创build了一个有名的互斥体,以确保进程之间的正确同步。 但是这似乎还不够。 根据MSDN,这在一个进程内工作,但不在不同进程之间。 接下来,我试图在每次写入之后调用FlushFileBuffers,而互斥量仍然保持不变,但数据仍然像这样失真

格式是时间进程ID /线程ID方法进入/离开/严重性命名空间+方法,然后消息文本。

10:29:42.994 7448/2236 }} Dll2.Test.fndll2 L1 -> Duration: 0.094s 10:29:43.040 7448/2236 {{ Dll2.DllMain L1 10:29:43.134 7448/2236 Info Dll2.DllMain L1 Process detach 10:29:43.181 7448/2236 }} Dll2.DllMain L1 -> Duration: 0.141s }} Dll2.DllMain L1 -10:29:42.681 7448/2236 Info Dll1.DllMain L1 Process attach 10:29:42.728 7448/2236 }} Dll1.DllMain L1 -10:29:42.744 2216/5510:29:42.775 7448/2236 {{ Dll1.Test.fndll1 10:210:29:42.822 7448/2236 Info Dll1.Test.fndll1 10:29:42.837 2216/557610:29:42.853 7448/2236 }} Dll1.Test.fndll1 L110:29:42.884 2216/557610:29:43.306 7448/2236 {{ Dll1.DllMain L1 10:29:43.353 7448/2236 Info Dll1.DllMain L1 Process detach 10:29:43.400 7448/2236 }} Dll1.DllMain L1 -> Duration: 0.094s 

我已经看过FILE_FLAG_NO_BUFFERING,但它有严重的限制,似乎不容易使用 。

有没有人知道正确的方式来写同步到同一个文件没有扭曲输出?

此致,

阿洛伊斯·克劳斯

Solutions Collecting From Web of "从不同的进程可靠地写入相同的文件"

我终于搞定了。 诀窍就是在文件写完之前在文件末尾寻找。 否则,我会覆盖大约一半的输出,尽管在每次写入之前我都使用跨进程互斥来锁定。

代码看起来像这样

 __int64 Seek (HANDLE hf, __int64 distance, DWORD MoveMethod) // from MSDN { LARGE_INTEGER li; li.QuadPart = distance; li.LowPart = SetFilePointer (hf, li.LowPart, &li.HighPart, MoveMethod); if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { li.QuadPart = -1; } return li.QuadPart; } void WriteToFile(TCHAR *pData) { DWORD dwWritten = 0; if( FALSE == ::WriteFile(_hFile, pData, _tcslen(pData)*sizeof(TCHAR), &dwWritten, NULL) ) { _LastError = ::GetLastError(); ASSERT__(FALSE); } } virtual void Write(TCHAR *pStr) { if( _hWriteMutex != NULL ) { DWORD res = ::WaitForSingleObject(_hWriteMutex, 120*1000); if( res == WAIT_OBJECT_0 || res == WAIT_ABANDONED ) // another process might have crashed while holding the mutex { // Ensure that we are really writing at the end of the file __int64 fPos = Seek(_hFile, 0, FILE_END); WriteToFile(pStr); ::ReleaseMutex(_hWriteMutex); } else { ASSERT__(FALSE); } } else { WriteToFile(pStr); } } 

SQLite使用文件锁来确保在从多个进程访问数据库文件时不会发生这种情况。 你有没有尝试过使用LockFile ? ( 例子 )。 过去,我使用SQLite数据库来记录多个进程,但在这种情况下可能会有点太多。

我不知道这个“正确”的方法,但是你现在所做的事似乎是正确的。 我能想到的下一个可能的解决方案是写入这个文件的一个专门的过程。 其余的进程将通过命名管道和(可能)互斥体与日志进程进行通信。

也许你甚至可以设置它,以便没有明确的过程,但其中一个正在运行的进程(首先启动的进程)承担了这个角色。 当这个过程结束并且需要将文件的所有权传递给另一个进程时,当然会有进一步的复杂性。 总而言之,这不是一个非常漂亮的解决方案,但如果一切都失败了,它应该可以工作。

虽然我怀疑还有一些我们都没有想过的东西,因为有些程序成功地使用了文件进行通信。

嗯…第二个想法 – 你已经有时间戳可用。 为什么不建立一个按时间戳记排序的浏览工具呢? 这样,缓存在哪里并不重要。

哦,还有三分之一 – 你试过内存映射的I / O吗? 这是不同的组织,它可能能够解决你的问题(更不用说更有效率)。

作为一个起点,我建议放弃共享写入模式,并使用您的命名互斥体来管理对文件的独占访问。 如果一切正常,应该给你正确的输出。 然后做一些性能测试,看看你是否可以像这样操作 – 你可能会发现这是足够的。

您必须保护或同步对使用命名互斥锁写入文件的函数的并发调用。 请参阅CreateMutex