共享内存 同步、互斥

共享内存没有提供互斥机制,需要程序员自己实现。

1.对于多个进程共享的共享内存来说,惟一可靠的互斥机制 就是带SEM_UNDO的system V信号量

原因:

    某一个进程在持有锁期间意外退出,所持有的锁还没有来得及释放,这回造成 所有等待(P操作)这个锁的进程/线程死锁。

所以不建议使用POSIX 信号量或者互斥锁。

2.对于同步机制,可以使用POSIX匿名信号量 。

3 .对于异步通知机制,可以使用 FIFO 或者eventfd(>since Linux 2.6.27


4.关于原子的创建共享内存

(1)创建任何东西先带着O_CREAT | O_EXCL去创建,失败了则直接打开,这是原子性必备的。
(2)共享内存初始化之前如何同步? 设置mode的X位后开始初始化共享内存,结束后取消X位,任何进程打开共享内存后stat轮询检查X位是否复位,复位后才可以开始操作。

在MFC中实现共享内存同步机制,通常需要结合Windows API提供的同步对象来完成。共享内存本身不提供同步功能,因此必须通过互斥体(Mutex)、事件(Event)或信号量(Semaphore)等机制来确保多个进程对共享内存的访问是线程安全和同步的。 ### 使用互斥体实现共享内存同步 互斥体是一种常用的同步机制,可以确保在同一时刻只有一个进程能够访问共享内存区域。以下是一个使用互斥体进行同步的示例代码: ```cpp // 创建或打开互斥体 HANDLE hMutex = CreateMutex(NULL, FALSE, _T("SharedMemoryMutex")); if (hMutex == NULL) { AfxMessageBox(_T("创建互斥体失败")); return; } // 打开共享内存映射文件 HANDLE hMapFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, _T("SharedMemoryName")); if (hMapFile == NULL) { AfxMessageBox(_T("打开共享内存映射文件失败")); CloseHandle(hMutex); return; } // 映射共享内存 LPVOID pSharedMemory = MapViewOfFile(hMapFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if (pSharedMemory == NULL) { AfxMessageBox(_T("映射共享内存失败")); CloseHandle(hMapFile); CloseHandle(hMutex); return; } // 访问共享内存前等待互斥体 WaitForSingleObject(hMutex, INFINITE); // 在此处进行共享内存的操作 // 例如:写入数据到共享内存 memcpy(pSharedMemory, "Hello from Process A", sizeof("Hello from Process A")); // 释放互斥体 ReleaseMutex(hMutex); // 清理资源 UnmapViewOfFile(pSharedMemory); CloseHandle(hMapFile); CloseHandle(hMutex); ``` ### 使用事件实现共享内存同步 事件对象也可以用于控制对共享内存的访问,尤其适用于通知其他进程某个操作已完成的情况。以下是使用事件进行同步的示例代码: ```cpp // 创建或打开事件 HANDLE hWriteEvent = CreateEvent(NULL, FALSE, TRUE, _T("WriteEvent")); if (hWriteEvent == NULL) { AfxMessageBox(_T("创建写事件失败")); return; } HANDLE hReadEvent = CreateEvent(NULL, FALSE, FALSE, _T("ReadEvent")); if (hReadEvent == NULL) { AfxMessageBox(_T("创建读事件失败")); CloseHandle(hWriteEvent); return; } // 打开共享内存映射文件 HANDLE hMapFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, _T("SharedMemoryName")); if (hMapFile == NULL) { AfxMessageBox(_T("打开共享内存映射文件失败")); CloseHandle(hWriteEvent); CloseHandle(hReadEvent); return; } // 映射共享内存 LPVOID pSharedMemory = MapViewOfFile(hMapFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if (pSharedMemory == NULL) { AfxMessageBox(_T("映射共享内存失败")); CloseHandle(hMapFile); CloseHandle(hWriteEvent); CloseHandle(hReadEvent); return; } // 等待写事件 WaitForSingleObject(hWriteEvent, INFINITE); // 在此处进行共享内存的操作 // 例如:读取数据 CString strData; strData.Format(_T("%s"), (LPCTSTR)pSharedMemory); // 设置读事件 SetEvent(hReadEvent); // 清理资源 UnmapViewOfFile(pSharedMemory); CloseHandle(hMapFile); CloseHandle(hWriteEvent); CloseHandle(hReadEvent); ``` ### 使用文件映射实现共享内存 MFC还提供了`CFileMapping`类来简化文件映射的创建和管理。以下是一个使用`CFileMapping`实现共享内存的示例: ```cpp // 定义共享内存结构体 struct SharedData { int nValue; TCHAR szText[256]; }; // 创建文件映射对象 CFileMapping fileMapping; fileMapping.Create(L"SharedMemoryName", sizeof(SharedData), PAGE_READWRITE); // 获取共享内存指针 SharedData* pData = (SharedData*)fileMapping.MapView(); if (pData != NULL) { // 写入数据 pData->nValue = 12345; _tcscpy_s(pData->szText, _T("Hello from Process A")); // 解除映射 fileMapping.UnmapView(); } ``` ### 同步机制的选择与比较 - **互斥体**:适合需要独占访问共享内存的场景,确保一次只有一个进程可以修改数据。 - **事件**:适合需要在不同进程之间传递状态变化的场景,如生产者-消费者模型。 - **信号量**:适合需要控制多个进程同时访问共享内存的场景,限制并发访问的数量。 选择合适的同步机制取决于具体的应用需求。如果只是简单的读写操作,互斥体可能是最直接的选择;如果涉及到复杂的进程间通信,事件或信号量可能更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值