【发布时间】:2015-04-22 05:53:00
【问题描述】:
在访问一组共享文件时,从多个同时运行的进程调用以下代码。这些文件包含条目的列表。 (我之所以提到文件 (pl.) 只是因为带有 entries 的实际列表在磁盘上被分解成更小的文件。)
规定每个条目必须有一个唯一的自增ID。为此,我正在为文件访问同步实现一个命名互斥锁,但显然我仍然遗漏了一些东西,因为有时我在这些 条目 中得到重复或重复的 ID(下面的 dwUniqueID 变量) .
有人能说明原因吗?
接下来是简短的代码,为简洁起见,省略了所有错误检查。我还将它剥离为裸 API 调用:
//Global variables
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hMutex = NULL;
然后初始化(完成一次):
//INFO: Error checks are omitted for brevity!
PSECURITY_DESCRIPTOR psdMutex = NULL;
::ConvertStringSecurityDescriptorToSecurityDescriptor(
L"D:(A;;GA;;;WD)(A;;GA;;;AN)S:(ML;;;;;S-1-16-0)",
SDDL_REVISION_1, &psdMutex, NULL);
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = psdMutex;
//Create global IPC mutex
hMutex = ::CreateMutex(&sa, FALSE, L"Global\\My_IPC_Mutex_Name");
::LocalFree(psdMutex);
然后第一次打开所需的文件之一:
//INFO: Error checks are omitted for brevity!
//Open initial file
ReopenFile();
void ReopenFile()
{
//Close previous file
if(hFile != INVALID_HANDLE_VALUE)
{
::FlushFileBuffers(hFile);
::CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
//Create/open file
hFile = ::CreateFile(strFilePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL);
}
然后,为了测试我的 IPC 同步,我在一个长循环中调用以下代码:
//INFO: Error checks are omitted for brevity!
for(;;){
//Enter IPC critical section
if(::WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0)
{
//Read last DWORD from file
DWORD dwUniqueID = 0, ncbWrtn;
LARGE_INTEGER liFileSz = {0};
::GetFileSizeEx(hFile, &liFileSz);
if(liFileSz.QuadPart >= sizeof(DWORD))
{
LARGE_INTEGER li0;
li0.QuadPart = -(LONGLONG)(sizeof(DWORD));
::SetFilePointerEx(hFile, li0, NULL, FILE_END);
::ReadFile(hFile, &dwUniqueID, sizeof(DWORD), &ncbWrtn, NULL);
}
//Do other work
//...
if(CheckIfThisFileIsFull(liFileSz))
{
//File must be closed and another one opened
ReopenFile();
}
//Increment unique ID
dwUniqueID++;
//And write it into file
LARGE_INTEGER li1 = {0};
::SetFilePointerEx(hFile, li1, NULL, FILE_END);
::WriteFile(hFile, &dwUniqueID, sizeof(DWORD), &ncbWrtn, NULL);
//Flush file
::FlushFileBuffers(hFile);
//Leave IPC critical section
::ReleaseMutex(hMutex);
}
else break;
}
【问题讨论】:
-
使用文件锁定(LockFile 等)而不是互斥锁可能更明智。
标签: c++ windows winapi synchronization ipc