IPC典型模型-哲学家纠缠问题
Posted yuanshijie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IPC典型模型-哲学家纠缠问题相关的知识,希望对你有一定的参考价值。
1965年dijkstra提出了一个关于进程同步问题,大致意思如下:
有5个哲学家坐在一张圆桌上,每个哲学家左右两边各有一个叉子。
只有当集齐两个叉子,才能够吃饭,否则哲学家就得乖乖去思考。
桌子上就5个叉子,理论上同时可以让两个哲学家进餐,那么怎么用两个进程来模拟这个状态呢?
0x001
这几个哲学家可以视作一个进程开了5次。我们来创建一个哲学家进程,代码如下:
用_tagCOMMUNICATIONOBJECT存放公共的数据,放在公共的内存中。
#include "stdafx.h" #include <Windows.h> #include<iostream> #define EATING_TIME 1000 #define PHILOSOPHER_COUNT 5 #define WM_INVALIDATE WM_USER + 1 //公用的数据,放到映射的内存中的数据 using namespace std; typedef struct _tagCOMMUNICATIONOBJECT { HWND hWnd; bool bExitApplication; int iPhilosopherArray[PHILOSOPHER_COUNT]; int PhilosopherCount; } COMMUNICATIONOBJECT, * PCOMMUNICATIONOBJECT; void Eat();//吃饭饭 TCHAR* szSemaphoreName = TEXT("__PD_SEMAPHORE__");//信号量名称 TCHAR* szMappingName = TEXT("__SHARED_FILE_MAPPING__");//映射内存名称 bool bExitApplication = false;//退出应用标志 int _tmain(int argc, _TCHAR* argv[]) { //获取控制台句柄 HWND Hconsole = GetConsoleWindow(); ShowWindow(Hconsole, SW_HIDE);//隐藏控制台窗口 int index = (int)_tcstol(argv[0], NULL, 10);//获取当前进程代号 //读取映射内容 HANDLE hMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szMappingName); if (!hMapping) { cout << "hMapping打开失败!" << endl; cout << GetLastError() << endl; return -1; }//映射内容一旦打开,未关闭时,一直处于可操作状态 while (!bExitApplication) { //打开信号量 HANDLE hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, szSemaphoreName); if (!hSemaphore) { cout << "sempahore创建失败!" << endl; cout << GetLastError() << endl; return -1; } //等待信号量触发 WaitForSingleObject(hSemaphore, INFINITE);//等待信号对象 //从映射对象中读取通用变量 PCOMMUNICATIONOBJECT pcomobj = (PCOMMUNICATIONOBJECT)MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(COMMUNICATIONOBJECT)); if (!pcomobj) { cout << "pcomobj创建失败!" << endl; cout << GetLastError() << endl; return -1; } bExitApplication = pcomobj->bExitApplication;//获取循环标志 if (!pcomobj->iPhilosopherArray[(index + pcomobj->PhilosopherCount - 1) % pcomobj->PhilosopherCount] && !pcomobj->iPhilosopherArray[(index + pcomobj->PhilosopherCount + 1) % pcomobj->PhilosopherCount]) { pcomobj->iPhilosopherArray[index] = 1; Eat();//吃饭 } SendMessage(pcomobj->hWnd, WM_INVALIDATE, 0, 0);//向另一个窗口发送消息 pcomobj->iPhilosopherArray[index] = 0;//吃完饭置为0 ReleaseSemaphore(hSemaphore, 1, NULL);//针对一个信号量 UnmapViewOfFile(pcomobj);//关闭文件映射 CloseHandle(hSemaphore);//关闭信号量句柄 } CloseHandle(hMapping);//关闭文件映射句柄 return 0;//返回 } void Eat() { Sleep(EATING_TIME);//停顿一段时间用于吃饭 }
0x02
创建一个进程来控制哲学家进餐
#include "stdafx.h" #include<iostream> using namespace std; #define BUTTON_CLOSE 100 #define PHILOSOPHER_COUNT 5 #define WM_INVALIDATE WM_USER + 1 typedef struct _tagCOMMUNICATIONOBJECT { HWND hWnd; bool bExitApplication; int iPhilosopherArray[PHILOSOPHER_COUNT]; int PhilosopherCount; } COMMUNICATIONOBJECT, *PCOMMUNICATIONOBJECT; HWND InitInstance(HINSTANCE hInstance, int nCmdShow); ATOM MyRegisterClass(HINSTANCE hInstance); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); int PhilosopherPass(int iPhilosopher); void FillEllipse(HWND hWnd, HDC hDC, int iLeft, int iTop, int iRight, int iBottom, int iPass); TCHAR* szTitle = TEXT("Philosophers Dinner Demo"); TCHAR* szWindowClass = TEXT("__PD_WND_CLASS__"); TCHAR* szSemaphoreName = TEXT("__PD_SEMAPHORE__"); TCHAR* szMappingName = TEXT("__SHARED_FILE_MAPPING__"); PCOMMUNICATIONOBJECT pCommObject = NULL; int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { //未使用的变量不出现警告 UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); HANDLE hMapping = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, sizeof(COMMUNICATIONOBJECT), szMappingName); if (!hMapping) { cout << "hMapping为空!" << endl; cout << GetLastError() << endl; return -1; } pCommObject = (PCOMMUNICATIONOBJECT)MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (!pCommObject) { cout << "pcommobject为空!" << endl; cout << GetLastError() << endl; return -1; } HANDLE hSemaphore = CreateSemaphore(NULL, (PHILOSOPHER_COUNT / 2), (PHILOSOPHER_COUNT / 2),szSemaphoreName); if (!hSemaphore) { cout << "hsemaphore为空!" << endl; cout << GetLastError() << endl; return -1; } InitCommonControls();//初始化通用控件 MyRegisterClass(hInstance);//注册 HWND hwnd = InitInstance(hInstance,nCmdShow);//初始化 if (!hwnd) { cout << "hwnd为空!" << endl; cout << GetLastError() << endl; return -1; } pCommObject->hWnd = hwnd; pCommObject->bExitApplication = false; pCommObject->PhilosopherCount = PHILOSOPHER_COUNT; memset(pCommObject->iPhilosopherArray, 0,sizeof(*pCommObject->iPhilosopherArray)); //开启进程 STARTUPINFO starupinfo[PHILOSOPHER_COUNT] = { {0},{0},{0},{0},{0} }; PROCESS_INFORMATION processInfo[PHILOSOPHER_COUNT]= { {0},{0},{0},{0},{0} }; HANDLE hProcess[PHILOSOPHER_COUNT] = { 0 }; TCHAR szBuffer[8] = {0}; for (int i = 0; i < PHILOSOPHER_COUNT; i++) { wsprintf(szBuffer, TEXT("%d"), i); if (CreateProcess(TEXT("..\Debug\Philosopher.exe"), szBuffer, NULL, NULL, FALSE, NULL, NULL, NULL, &starupinfo[i], &processInfo[i])) { hProcess[i] = processInfo[i].hProcess; } } MSG msg = { 0 }; while (GetMessage(&msg, hwnd, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } pCommObject->bExitApplication = true; UnmapViewOfFile(pCommObject);//关闭文件映射 for (int i = 0; i < PHILOSOPHER_COUNT; i++) { CloseHandle(hProcess[i]);//关闭进程句柄 } CloseHandle(hMapping); return (int)msg.wParam;//返回消息参数0 } //ATOM==word ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wndEx; wndEx.cbSize = sizeof(WNDCLASSEX); wndEx.style = CS_HREDRAW | CS_VREDRAW; wndEx.lpfnWndProc = WndProc; wndEx.cbClsExtra = 0; wndEx.cbWndExtra = 0; wndEx.hInstance = hInstance; wndEx.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); wndEx.hCursor = LoadCursor(NULL, IDC_ARROW); wndEx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wndEx.lpszMenuName = NULL; wndEx.lpszClassName = szWindowClass; wndEx.hIconSm = LoadIcon(wndEx.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); return RegisterClassEx(&wndEx); } //初始化 HWND InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 200, 200, 540, 590, NULL, NULL, hInstance, NULL); if (!hWnd) { return NULL; } HFONT hFont = CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN, TEXT("Microsoft Sans Serif")); HWND hButton = CreateWindow(TEXT("BUTTON"), TEXT("Close"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP, 410, 520, 100, 25, hWnd, (HMENU)BUTTON_CLOSE, hInstance, NULL); SendMessage(hButton, WM_SETFONT, (WPARAM)hFont, TRUE); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return hWnd; } //回调函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_COMMAND: { switch (LOWORD(wParam)) { case BUTTON_CLOSE: { DestroyWindow(hWnd); break; } } break; } case WM_INVALIDATE: { //更新指定的窗口区域 InvalidateRect(hWnd, NULL, TRUE);//接受philosopher发来的消息,进行处理 break; } case WM_PAINT: { PAINTSTRUCT paintStruct; HDC hDC = BeginPaint(hWnd, &paintStruct); FillEllipse(hWnd, hDC, 210, 10, 310, 110, PhilosopherPass(1));//圆圈1 FillEllipse(hWnd, hDC, 410, 170, 510, 270, PhilosopherPass(2));//圆圈2 FillEllipse(hWnd, hDC, 335, 400, 435, 500, PhilosopherPass(3));//圆圈3 FillEllipse(hWnd, hDC, 80, 400, 180, 500, PhilosopherPass(4));//圆圈4 FillEllipse(hWnd, hDC, 10, 170, 110, 270, PhilosopherPass(5));//圆圈5 EndPaint(hWnd, &paintStruct);//结束绘制 break; } case WM_DESTROY: { PostQuitMessage(0); break; } default: { return DefWindowProc(hWnd, uMsg, wParam, lParam); } } return 0; } //哲学家 int PhilosopherPass(int iPhilosopher) { return pCommObject->iPhilosopherArray[iPhilosopher - 1]; } //填充圆圈 void FillEllipse(HWND hWnd, HDC hDC, int iLeft, int iTop, int iRight, int iBottom, int iPass) { HBRUSH hBrush = NULL; if (iPass)//哲学家状态非0,填充红色 { hBrush = CreateSolidBrush(RGB(255, 0, 0)); } else//哲学家状态为0,填充白色 { hBrush = CreateSolidBrush(RGB(255, 255, 255)); } HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);//选中画刷1 Ellipse(hDC, iLeft, iTop, iRight, iBottom);//绘制圆形 SelectObject(hDC, hOldBrush);//填充颜色 DeleteObject(hBrush);//用完之后清空选中的句柄 }
以上是关于IPC典型模型-哲学家纠缠问题的主要内容,如果未能解决你的问题,请参考以下文章