cpp
创建共享内存使用的名称前边能不能加global,像global\test这种?
可以,而且这正是推荐的做法!
使用 Global\ 前缀可以让共享内存在不同会话(session)之间共享。
Global 和 Local 命名空间
cpp
1. 全局命名空间 (Global Namespace)
前缀: Global\
作用: 对象在所有会话中可见
权限要求: 需要管理员权限(或相应权限)来创建
使用场景: 服务与用户程序通信、跨会话进程通信
2. 本地命名空间 (Local Namespace)
前缀: Local\ (默认,可以省略)
作用: 对象仅在当前会话中可见
权限要求: 普通用户权限即可
使用场景: 同一会话内的进程通信
代码示例
示例1:创建全局共享内存(需要管理员权限)
cpp
cpp
#include <windows.h>
#include <iostream>
int main() {
// 全局共享内存 - 注意:需要管理员权限运行
HANDLE hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
1024,
L"Global\\MySharedMemory"); // 使用 Global\ 前缀
if (hMapFile == NULL) {
DWORD dwError = GetLastError();
std::cout << "CreateFileMapping failed. Error: " << dwError << std::endl;
if (dwError == ERROR_ACCESS_DENIED) {
std::cout << "可能需要管理员权限来创建 Global\\ 对象" << std::endl;
}
return 1;
}
std::cout << "全局共享内存创建成功!" << std::endl;
// ... 使用共享内存 ...
CloseHandle(hMapFile);
return 0;
}
示例2:创建本地共享内存(普通权限)
cpp
cpp
// 本地共享内存 - 普通用户权限即可
HANDLE hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
1024,
L"Local\\MySharedMemory"); // Local\ 前缀,可以省略为 "MySharedMemory"
完整示例:带权限设置的全局共享内存
cpp
cpp
#include <windows.h>
#include <iostream>
#include <sddl.h>
int main() {
// 1. 创建安全描述符,允许所有访问(仅示例,生产环境应更严格)
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); // NULL DACL = 允许所有访问
// 2. 设置安全属性
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
// 3. 创建全局共享内存
HANDLE hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
&sa, // 使用安全属性
PAGE_READWRITE,
0,
1024,
L"Global\\MyAppSharedMemory");
if (hMapFile == NULL) {
DWORD err = GetLastError();
std::cout << "创建失败,错误码: " << err << std::endl;
switch (err) {
case ERROR_ACCESS_DENIED:
std::cout << "错误:访问被拒绝。可能需要:\n";
std::cout << "1. 以管理员身份运行\n";
std::cout << "2. 设置正确的安全描述符\n";
break;
case ERROR_ALREADY_EXISTS:
std::cout << "错误:共享内存已存在\n";
break;
}
return 1;
}
std::cout << "全局共享内存创建成功!" << std::endl;
// 4. 检查是否是新创建的
if (GetLastError() == ERROR_ALREADY_EXISTS) {
std::cout << "(共享内存已存在,打开现有对象)" << std::endl;
}
// 5. 其他进程访问这个共享内存
std::cout << "\n其他进程可以通过以下名称访问:\n";
std::cout << "Global\\\\MyAppSharedMemory" << std::endl;
CloseHandle(hMapFile);
return 0;
}
跨会话访问示例
cpp
进程A(创建者):
cpp
// 以管理员权限运行
HANDLE hMap = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
1024,
L"Global\\MyGlobalMemory");
进程B(访问者,可在不同会话中):
cpp
// 普通用户权限即可打开(如果权限允许)
HANDLE hMap = OpenFileMapping(
FILE_MAP_ALL_ACCESS,
FALSE,
L"Global\\MyGlobalMemory"); // 相同的全局名称
重要注意事项
cpp
权限问题:
创建 Global\ 对象需要 SeCreateGlobalPrivilege 权限
通常需要以管理员身份运行
或者设置适当的安全描述符
会话隔离:
Windows 系统有会话隔离机制(Session 0, 1, 2...)
服务运行在 Session 0
用户程序运行在其他会话
Global\ 可以跨这些会话通信
名称格式:
最大长度:260 个字符
区分大小写
不能包含反斜杠(除了命名空间前缀)
清理:
确保所有进程都关闭句柄
最后一个句柄关闭时,系统会自动清理共享内存
调试技巧
cpp
如果遇到权限问题,可以:
使用 whoami /priv 查看当前权限
在代码中检查 ERROR_ACCESS_DENIED (5)
使用 Process Explorer 查看已创建的共享内存对象
这种 Global\ 前缀的方式在需要服务与用户界面通信、远程桌面会话间通信等场景非常有用!