我有2个程序。 第一个程序将打开第二个程序,还将创建2个用于同步的事件对象。 第二个(将要打开的对象)将打开这两个Event对象。 这两个程序都将运行一个for循环,以模拟从内存进行的写入和读取操作。
程序一:
read = CreateEvent(NULL, false, false, "READ");
write = CreateEvent(NULL, false, false, "WRITE");
CreateProcess("PATH_TO_EXE", NULL, NULL, NULL, FALSE, NULL, 0, NULL, &startupInfo, &processInformation);
for (int i = 1; i <= 100; i++)
{
printf("Wrote data to memory\n");
SetEvent(write);
WaitForSingleObject(read, INFINITE);
}
程序二:
HANDLE read, write;
read = OpenEvent(EVENT_MODIFY_STATE, false, "READ");
write = OpenEvent(EVENT_MODIFY_STATE, false, "WRITE");
for (int i = 1; i <= 100; i++)
{
WaitForSingleObject(write, INFINITE);
printf("Read data from memory.\n");
SetEvent(read);
}
我希望输出为:
Wrote data to memory.
Read data from memory.
Wrote data to memory.
Read data from memory.
....
但实际输出如下:
Wrote data to memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Wrote data to memory.
Read data from memory.
Wrote data to memory.
Wrote data to memory.
Read data from memory.
...
在某些时候它只是挂起,这意味着死锁。但是我不确定这怎么可能。有帮助吗?
答案 0 :(得分:2)
对于WaitForSingleObject
-对象的句柄(第1个参数)必须具有SYNCHRONIZE
访问权限。否则api失败,并显示ERROR_ACCESS_DENIED
。但您致电
write = OpenEvent(EVENT_MODIFY_STATE, false, "WRITE");
请求的访问权限不包括您需要的SYNCHRONIZE
,也包括您在此代码中实际上不需要的EVENT_MODIFY_STATE
。因此您需要将代码更改为
write = OpenEvent(SYNCHRONIZE, false, "WRITE");
您也不会检查任何api调用的结果。如果这样做-您仅查看WaitForSingleObject(write, INFINITE);
返回WAIT_FAILED
和GetLastError() == ERROR_ACCESS_DENIED
。
如果您还需要通过带有子进程的这两个事件来需要ipc,请更好地创建未命名和继承的ipc,然后通过命令行将其值传递给child。如果您只想测试事件工作逻辑-更容易使用单独的线程而不是新进程。该测试代码如下所示:
ULONG WINAPI child(void* p)
{
if (HANDLE read = OpenEvent(EVENT_MODIFY_STATE, false, L"READ"))
{
if (HANDLE write = OpenEvent(SYNCHRONIZE, false, L"WRITE"))
{
ULONG i = (ULONG)(ULONG_PTR)p;
do
{
if (WaitForSingleObject(write, INFINITE) == WAIT_FAILED){
DbgPrint("2:%u\n", GetLastError());
break;
}
DbgPrint("Read data from memory.\n");
if (!SetEvent(read)){
DbgPrint("3:%u\n", GetLastError());
break;
}
} while (--i);
CloseHandle(write);
}
CloseHandle(read);
}
return 0;
}
void bfg()
{
if (HANDLE read = CreateEvent(NULL, false, false, L"READ"))
{
if (HANDLE write = CreateEvent(NULL, false, false, L"WRITE"))
{
ULONG i = 16;
if (HANDLE hThread = CreateThread(0, 0, child, (PVOID)(ULONG_PTR)i, 0, 0))
{
do
{
DbgPrint("Wrote data to memory\n");
if (!SetEvent(write) || WaitForSingleObject(read, INFINITE) == WAIT_FAILED){
DbgPrint("1:%u\n", GetLastError());
break;
}
} while (--i);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
CloseHandle(write);
}
CloseHandle(read);
}
}
有趣的是,早期(在赢得8.1之前)是Windows中的 EventPair 对象,该对象是为此类任务而设计的。但原因不明