VC中共享内存的命名空间

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\ 前缀的方式在需要服务与用户界面通信、远程桌面会话间通信等场景非常有用!

相关推荐
dragoooon342 小时前
[C++——lesson30.数据结构进阶——「红黑树」]
开发语言·数据结构·c++
云泽8082 小时前
C++ STL 栈与队列完全指南:从容器使用到算法实现
开发语言·c++·算法
历程里程碑3 小时前
C++ 17异常处理:高效捕获与精准修复
java·c语言·开发语言·jvm·c++
xu_yule3 小时前
算法基础(背包问题)—分组背包和混合背包
c++·算法·动态规划·分组背包·混合背包
你的冰西瓜3 小时前
C++中的vector容器详解
开发语言·c++·stl
刻BITTER3 小时前
C++ 获取任意整数类型的最大、最小值和长度
开发语言·c++
程序员老舅3 小时前
C++ STL 算法:从原理到工程实践
linux·c++·stl·c/c++·数据结构与算法
十五年专注C++开发3 小时前
ZeroMQ: 一款高性能、异步、轻量级的消息传输库
网络·c++·分布式·zeroqm
superman超哥4 小时前
仓颉语言中循环语句(for/while)的深度剖析与工程实践
c语言·开发语言·c++·python·仓颉