进程间通过内核对象共享数据失败:OpenFileMapping返回NULL
我正在学习Pavel Yosifovich的书籍和视频,尝试用纯C编写程序,通过内核对象实现两个进程间的文本字符串传递。但读取进程中OpenFileMapping始终返回NULL,GetLastError返回错误码2(文件未找到)。我用WinObj工具看到MySharedMemory对象存在于\Sessions\2\BaseNamedObjects\MySharedMemory路径下,排除了权限问题,尝试将名称改为Local\MySharedMemory也没用,管理员身份运行同样无法解决,推测是路径相关问题。
初始代码
生产者代码
#include <windows.h> #include <stdio.h> #include <string.h> int main() { HANDLE hFileMapping; LPVOID lpFileMap; char buffer[] = "Windows System Programming is fun!"; hFileMapping = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(buffer), L"MySharedMemory" ); if (hFileMapping == NULL) { printf("Error creating file mapping: %d\n", GetLastError()); return 1; } lpFileMap = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0); if (lpFileMap == NULL) { printf("Error mapping view of file: %d\n", GetLastError()); CloseHandle(hFileMapping); return 1; } strcpy((char*)lpFileMap, buffer); printf("Data written to shared memory. Press Enter to exit...\n"); getchar(); UnmapViewOfFile(lpFileMap); CloseHandle(hFileMapping); return 0; }
消费者代码
#include <windows.h> #include <stdio.h> int main() { HANDLE hFileMapping; LPVOID lpFileMap; hFileMapping = OpenFileMapping( FILE_MAP_READ, FALSE, L"MySharedMemory" ); if (hFileMapping == NULL) { printf("Error opening file mapping: %d\n", GetLastError()); getchar(); return 1; } lpFileMap = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0, 0 ); if (lpFileMap == NULL) { printf("Error mapping view of file: %d\n", GetLastError()); CloseHandle(hFileMapping); getchar(); return 1; } printf("Received message: %s\n", (char*)lpFileMap); UnmapViewOfFile(lpFileMap); getchar(); CloseHandle(hFileMapping); return 0; }
修改后的代码(仍无法运行)
#include <windows.h> #include <stdio.h> #include <string.h> int main() { HANDLE hFileMapping; LPVOID lpFileMap; char buffer[] = "Windows System Programming is fun!"; hFileMapping = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1 << 12, L"MySharedMemory" ); if (hFileMapping == NULL) { printf("Error creating file mapping: %d\n", GetLastError()); return 1; } lpFileMap = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0); if (lpFileMap == NULL) { printf("Error mapping view of file: %d\n", GetLastError()); CloseHandle(hFileMapping); return 1; } strcpy((char*)lpFileMap, buffer); printf("Data written to shared memory. Press Enter to exit...\n"); getchar(); UnmapViewOfFile(lpFileMap); CloseHandle(hFileMapping); return 0; } #include <windows.h> #include <stdio.h> int main() { HANDLE hFileMapping; LPVOID lpFileMap; //hFileMapping = OpenFileMapping( // FILE_MAP_READ, // FALSE, // L"MySharedMemory" // ); hFileMapping = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1 << 12, L"MySharedMemory" ); if (hFileMapping == NULL) { printf("Error opening file mapping: %d\n", GetLastError()); getchar(); return 1; } lpFileMap = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 1 << 12 ); if (lpFileMap == NULL) { printf("Error mapping view of file: %d\n", GetLastError()); CloseHandle(hFileMapping); getchar(); return 1; } printf("Received message: %s\n", (char*)lpFileMap); UnmapViewOfFile(lpFileMap); getchar(); CloseHandle(hFileMapping); return 0; }
问题排查与解决
字符集不匹配:检查两个项目的编译字符集设置,必须保持一致(要么均为Unicode,要么均为多字节字符集)。如果生产者用Unicode编译(带
L前缀),消费者用多字节编译,会导致名称解析不匹配。统一字符集后,确保共享内存名称的写法完全一致(Unicode用L"xxx",多字节用"xxx")。会话与命名空间问题:如果两个进程不在同一个会话,尝试在名称前添加
Global\前缀(需管理员权限),比如L"Global\\MySharedMemory",且生产者和消费者必须使用相同前缀。生产者提前销毁对象:生产者在
getchar()后立即关闭句柄并销毁映射,若此时消费者未运行,共享内存对象会被系统回收。确保消费者运行时,生产者仍保持句柄打开。消费者代码逻辑错误:修改后的消费者用
CreateFileMapping替代OpenFileMapping,会创建新的共享内存对象而非打开已有对象。应恢复使用OpenFileMapping,并保证名称与生产者完全一致。
修正后的消费者示例(Unicode字符集):
#include <windows.h> #include <stdio.h> int main() { HANDLE hFileMapping; LPVOID lpFileMap; hFileMapping = OpenFileMapping( FILE_MAP_READ, FALSE, L"MySharedMemory" ); if (hFileMapping == NULL) { printf("Error opening file mapping: %d\n", GetLastError()); getchar(); return 1; } lpFileMap = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0 ); if (lpFileMap == NULL) { printf("Error mapping view of file: %d\n", GetLastError()); CloseHandle(hFileMapping); getchar(); return 1; } printf("Received message: %s\n", (char*)lpFileMap); UnmapViewOfFile(lpFileMap); getchar(); CloseHandle(hFileMapping); return 0; }
内容的提问来源于stack exchange,提问作者Chad Botting

