我有两个流程:
memory mapped region
,mutex
并生成
第二个过程。然后在memory mapped region
。memory mapped region
,opens the mutex
,然后读取process 1
写的数字。 我打算第一个进程写一对数字,第二个进程立即读取它。
process 2
似乎正在挨饿。
我做错了什么?
流程1:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
DWORD memSize = 400 * sizeof(DWORD);
HANDLE map_file = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, memSize, TEXT("mem1"));
if (map_file == NULL)
{
_tprintf(_T("(Parent) File mapping is null\n"));
return 1;
}
char* map_ptr = (char *) MapViewOfFile(map_file, FILE_MAP_READ, 0, 0, 0);
if (map_ptr == NULL)
{
_tprintf(_T("(Parent) PTR is null \n"));
}
HANDLE hMutex = CreateMutex(NULL, TRUE, _T("mt"));
LPTSTR szCmdline = _tcsdup(TEXT("C:\\Users\\cristi\\source\\repos\\process_synchronization_reader\\Debug\\process_synchronization_reader.exe"));
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
_tprintf(_T("Process created\n"));
}
_tprintf(_T("pare ca s-a creat"));
for (int i = 1; i <= 200; ++i)
{
WaitForSingleObject(hMutex, INFINITE);
_tprintf(_T("(Parent %d) writing from the parent\n"), i);
DWORD a, b;
CopyMemory((LPVOID) &a, map_ptr, sizeof(DWORD));
map_ptr += sizeof (DWORD);
CopyMemory((LPVOID) &b, map_ptr, sizeof(DWORD));
map_ptr += sizeof(DWORD);
ReleaseMutex(hMutex);
}
int n;
cin >> n;
CloseHandle(map_file);
return 0;
}
流程2:
#include "stdafx.h"
#include <windows.h>
int main()
{
HANDLE map_file = OpenFileMapping(FILE_MAP_READ, FALSE, TEXT("mem1"));
if (map_file == NULL)
{
_tprintf(_T("(Child) File mapping is null\n"));
return 1;
}
char* map_ptr = (char *) MapViewOfFile(map_file, FILE_MAP_READ, 0, 0, 0);
if (map_ptr == NULL)
{
_tprintf(_T("(Child) PTR is null \n"));
}
_tprintf(_T("(CHILD) BEfore reading the first number\n"));
HANDLE hMutex = OpenMutex(SYNCHRONIZE, TRUE, _T("mt"));
for (int i = 1; i <= 200; i++)
{
WaitForSingleObject(hMutex, INFINITE);
DWORD a = i;
DWORD b = 2 * i;
CopyMemory((LPVOID) map_ptr, &a, sizeof(DWORD));
map_ptr += sizeof(DWORD);
CopyMemory((LPVOID) map_ptr, &b, sizeof(DWORD));
map_ptr += sizeof(DWORD);
_tprintf(_T("[================================================]\n"));
_tprintf(_T("( %d %d )\n"), a, b);
_tprintf(_T("[=================================================]\n"));
ReleaseMutex(hMutex);
}
return 0;
}
答案 0 :(得分:1)
对于从共享内存获得顺序写入/读取,我们需要2个事件(让它命名为低和高)。
第一个帖子:
第二个帖子:
与此解决方案不同,互斥锁无法提供读/写序列。互斥保证直到一个线程将访问共享数据(读或写),另一个线程将不会在并发中执行此操作。但这不能连续多次阻止写入或读取。真的 - 在进程2开始时插入消息框 - 在他第一次尝试获取互斥锁之前 - 第一个进程已经很多次获取并释放互斥锁。或者如果一个线程将在释放和等待互斥之间暂停 - 同时另一个线程多次等待并释放它。所以代码看起来像:
struct SHARED_DATA
{
ULONG id;
ULONG nLoops;
BOOL bTask;
};
DWORD proc2(SHARED_DATA* p)
{
if (HANDLE hLowEvent = OpenEvent(SYNCHRONIZE, FALSE, L"LowEvent"))
{
if (HANDLE hHighEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, L"hHighEvent"))
{
ULONG id = GetCurrentThreadId();
for(;;)
{
if (WaitForSingleObject(hLowEvent, INFINITE) != WAIT_OBJECT_0)
{
break;
}
// ++ checking for sequence
if (p->id == id)
{
__debugbreak();// must never be
}
p->id = id;
// -- checking for sequence
if (!p->bTask)
{
// no more task
break;
}
// task done
p->bTask = FALSE;
// signal to #1
if (!SetEvent(hHighEvent))
{
break;
}
}
CloseHandle(hHighEvent);
}
CloseHandle(hLowEvent);
}
return 0;
}
DWORD proc1(SHARED_DATA* p)
{
if (HANDLE hLowEvent = CreateEvent(0, FALSE, FALSE, L"LowEvent"))
{
if (HANDLE hHighEvent = CreateEvent(0, FALSE, FALSE, L"hHighEvent"))
{
ULONG id = GetCurrentThreadId();
p->nLoops = 0x1000;
p->id = 0;
p->bTask = FALSE;
// exec proc2 here
goto __1;
do
{
if (WaitForSingleObject(hHighEvent, INFINITE) != WAIT_OBJECT_0)
{
break;
}
if (p->bTask)
{
__debugbreak();
}
// ++ checking for sequence
if (p->id == id)
{
__debugbreak();// must never be
}
__1:
p->id = id;
// -- checking for sequence
p->bTask = 0 < --p->nLoops;
// signal to #2
if (!SetEvent(hLowEvent))
{
break;
}
} while (p->nLoops);
CloseHandle(hHighEvent);
}
CloseHandle(hLowEvent);
}
return 0;
}
答案 1 :(得分:0)
您创建一个最初拥有的互斥锁(CreateMutex
的第二个参数是TRUE
),然后在其上调用等待函数。因此,即使在调用ReleaseMutex
之后,它仍然由第一个进程的主线程拥有。
将参数更改为FALSE
,或者跳过为{em>第一次循环迭代调用WaitForSingleObject
。