WINAPI的Windows Events能否实现不同进程间通信解决文件读写竞态?
跨进程使用Win32 Event同步方案解答
核心结论
完全可以实现跨进程同步,Win32 Event属于内核对象,本身原生支持跨进程访问,你查到的同进程多线程使用示例只是它的常见应用场景之一,跨进程使用完全符合API设计预期。
实现原理
只要在创建Event时指定唯一的命名,另一个进程就可以通过相同的名称打开同一个Event内核对象,跨进程的信号通知效果和同进程内多线程同步完全一致。
适配你的场景的实现步骤
你需要创建两个命名Event来实现读写交替的逻辑:
writer_done:通知reader写入操作已完成,可以执行读取reader_done:通知writer读取操作已完成,可以执行下一次写入
初始状态设置
writer_done初始为未触发状态reader_done初始为触发状态,保证writer可以优先执行第一次写入
核心代码示例
通用Event创建逻辑(writer和reader进程通用)
#include <windows.h> #include <fstream> #include <iostream> #include <cstdlib> // 两个Event的名称,两个进程必须完全一致 const wchar_t* EVENT_WRITER_DONE = L"MyApp_WriterDone_Event"; const wchar_t* EVENT_READER_DONE = L"MyApp_ReaderDone_Event";
writer.exe核心逻辑
int main() { // 创建自动重置Event,reader_done初始为触发状态 HANDLE hWriterDone = CreateEventW(NULL, FALSE, FALSE, EVENT_WRITER_DONE); HANDLE hReaderDone = CreateEventW(NULL, FALSE, TRUE, EVENT_READER_DONE); if (hWriterDone == NULL || hReaderDone == NULL) { std::cerr << "CreateEvent failed, error: " << GetLastError() << std::endl; return 1; } while (true) { // 等待reader完成上一次读取 WaitForSingleObject(hReaderDone, INFINITE); // 执行写文件逻辑 std::fstream file("some_file.bin", std::ios::out | std::ios::binary | std::ios::trunc); int rand_val = rand(); file.write(reinterpret_cast<char*>(&rand_val), sizeof(rand_val)); file.close(); // 通知reader写入完成 SetEvent(hWriterDone); } // 进程退出前关闭句柄(示例中循环不会走到这里,实际生产环境要处理退出逻辑) CloseHandle(hWriterDone); CloseHandle(hReaderDone); return 0; }
reader.exe核心逻辑
int main() { // 打开和writer同名的两个Event HANDLE hWriterDone = CreateEventW(NULL, FALSE, FALSE, EVENT_WRITER_DONE); HANDLE hReaderDone = CreateEventW(NULL, FALSE, TRUE, EVENT_READER_DONE); if (hWriterDone == NULL || hReaderDone == NULL) { std::cerr << "OpenEvent failed, error: " << GetLastError() << std::endl; return 1; } while (true) { // 等待writer完成写入 WaitForSingleObject(hWriterDone, INFINITE); // 执行读文件逻辑 std::fstream file("some_file.bin", std::ios::in | std::ios::binary); int val; file.read(reinterpret_cast<char*>(&val), sizeof(val)); file.close(); std::cout << "Read integer: " << val << std::endl; // 通知writer读取完成 SetEvent(hReaderDone); } // 进程退出前关闭句柄 CloseHandle(hWriterDone); CloseHandle(hReaderDone); return 0; }
注意事项
- 两个进程使用的Event名称必须完全一致,建议添加自定义前缀避免和系统其他内核对象重名
- 如果需要在不同用户会话下的进程通信,需要给Event名称加
Global\前缀,同时进程需要申请管理员权限 - 示例中使用自动重置Event(CreateEvent第二个参数为FALSE),WaitForSingleObject返回后会自动重置Event为未触发状态,无需手动调用
ResetEvent - 进程正常退出前务必调用
CloseHandle关闭Event句柄,避免内核资源泄漏
内容的提问来源于stack exchange,提问作者Aravind A
相关产品推荐
相关产品推荐

