使用VirtualAlloc实现跨进程固定基址共享内存的异常问题
跨进程指定地址共享内存的解决方案
嘿,这个问题的核心在于Windows每个进程的虚拟地址空间是完全独立的——你在第一个进程里用VirtualAlloc分配的0x80000000地址,只属于进程1自己的地址空间,进程2的这个地址区域默认是未映射的空白区域,直接访问当然会触发内存异常啦。
要实现两个进程在同一个虚拟地址访问共享内存,你得把CreateFileMapping(创建共享内存对象)和MapViewOfFileEx(带指定地址映射的版本)结合起来用,具体步骤如下:
步骤1:第一个进程(创建共享内存并映射到指定地址)
先创建一个命名的共享内存对象,然后把它映射到你想要的0x80000000地址:
// 创建共享内存文件映射对象 HANDLE hSharedMap = CreateFileMapping( INVALID_HANDLE_VALUE, // 用系统分页文件做后备存储 NULL, // 默认安全设置 PAGE_READWRITE, // 共享内存的读写权限 0, // 内存大小高32位(这里设0,64KB用低32位足够) 65536, // 共享内存大小:64KB L"FixedAddrSharedMem" // 共享内存的唯一名称,别和系统里的重名 ); if (hSharedMap == NULL) { // 处理创建失败的情况,比如调用GetLastError()查原因 return 1; } // 将共享内存映射到指定的0x80000000地址 LPVOID pMappedAddr = MapViewOfFileEx( hSharedMap, // 刚才创建的共享内存句柄 FILE_MAP_ALL_ACCESS, // 读写访问权限 0, // 文件偏移高32位(共享内存不用偏移,设0) 0, // 文件偏移低32位 65536, // 要映射的大小 (LPVOID)0x80000000LL // 关键!指定要映射到的虚拟地址 ); if (pMappedAddr == NULL) { // 映射失败,比如这个地址在进程1里已经被占用了 CloseHandle(hSharedMap); return 1; } // 现在你就可以直接用0x80000000地址读写共享内存了
步骤2:第二个进程(打开共享内存并映射到相同地址)
在第二个进程里,打开同一个共享内存对象,然后同样用MapViewOfFileEx映射到0x80000000:
// 打开已存在的共享内存对象 HANDLE hSharedMap = OpenFileMapping( FILE_MAP_ALL_ACCESS, // 和进程1一致的读写权限 FALSE, // 不继承句柄 L"FixedAddrSharedMem" // 必须和进程1的共享内存名称完全一致 ); if (hSharedMap == NULL) { // 打开失败,比如共享内存还没创建,或者权限不够 return 1; } // 映射到同一个0x80000000地址 LPVOID pMappedAddr = MapViewOfFileEx( hSharedMap, FILE_MAP_ALL_ACCESS, 0, 0, 65536, (LPVOID)0x80000000LL ); if (pMappedAddr == NULL) { // 映射失败,比如进程2的这个地址已经被其他内存占用了 CloseHandle(hSharedMap); return 1; } // 现在你可以直接访问0x80000000了,不会再触发内存异常 char c = *((const char*)0x80000000LL);
几个关键注意事项
- 必须用MapViewOfFileEx:普通的
MapViewOfFile不能指定映射地址,只有带Ex的版本支持这个功能。 - 地址必须在两个进程中都空闲:如果进程2的0x80000000地址已经被其他内存块占用,
MapViewOfFileEx会调用失败。这时候你可以先在进程2里用VirtualAlloc((LPVOID)0x80000000LL, 65536, MEM_RESERVE, PAGE_NOACCESS)预留这个地址,再进行映射。 - 权限要统一:两个进程的共享内存访问权限要保持一致,比如都用
FILE_MAP_ALL_ACCESS,避免权限不足的问题。
为什么你之前的方法行不通?
你在进程1里用VirtualAlloc分配的是进程私有内存,这块内存只属于进程1,进程2完全看不到它。只有通过CreateFileMapping创建的共享内存对象,才是系统级别的共享资源,能被多个进程访问;再通过MapViewOfFileEx指定相同地址映射,才能让两个进程在同一个虚拟地址上操作这块共享内存。
内容的提问来源于stack exchange,提问作者thfabian
相关产品推荐
相关产品推荐

