新闻中心

c++怎么创建一个跨平台的共享内存区域_C++中跨进程共享内存的实现方式

2025-11-06
浏览次数:
返回列表
使用内存映射文件可实现C++跨平台共享内存,Windows通过CreateFileMapping和MapViewOfFile,POSIX系统用shm_open与mmap,配合条件编译封装统一接口。示例代码展示创建、映射及访问共享内存区域,支持多进程数据共享。需注意名称唯一性、资源清理与同步机制。推荐使用Boost.Interprocess库简化开发,其提供跨平台抽象并集成同步原语,提升稳定性和开发效率。

c++怎么创建一个跨平台的共享内存区域_c++中跨进程共享内存的实现方式

在C++中实现跨平台的共享内存区域,关键在于使用可移植的API。由于不同操作系统对共享内存的支持方式不同(如Windows用映射文件,Linux/Unix用POSIX或System V),直接调用系统API会导致代码不可移植。推荐使用封装良好的跨平台机制,比如基于文件映射的内存映射方式,并借助条件编译或抽象接口统一操作。

使用内存映射文件(Memory-Mapped Files)

内存映射是实现跨平台共享内存最常用的方法。它将一个文件或共享对象映射到多个进程的地址空间,实现数据共享。

原理: 创建一个命名的共享内存区域(通常通过一个临时文件或操作系统支持的匿名共享对象),然后多个进程映射同一块区域进行读写。

Windows 和 POSIX 的兼容实现示例:

#include <string>
#include <cstdint>
#ifdef _WIN32
    #include <windows.h>
#else
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <errno.h>
#endif

class SharedMemory {
public:
    SharedMemory(const std::string& name, size_t size) : m_name(name), m_size(size), m_handle(nullptr), m_ptr(nullptr) {
        open();
    }

    ~SharedMemory() {
        close();
    }

    void* data() const { return m_ptr; }
    bool is_valid() const { return m_ptr != nullptr; }

private:
    void open() {
#ifdef _WIN32
        // Windows: 使用 CreateFileMapping 和 MapViewOfFile
        HANDLE hMapFile = CreateFileMappingA(
            INVALID_HANDLE_VALUE,    // 使用分页文件,而非磁盘文件
            nullptr,
            PAGE_READWRITE,
            0,
            static_cast<DWORD>(m_size),
            m_name.c_str()
        );

        if (hMapFile == nullptr) return;

        m_handle = hMapFile;
        m_ptr = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, m_size);
#else
        // POSIX: 使用 shm_open + mmap
        int fd = shm_open(m_name.c_str(), O_CREAT | O_RDWR, 0666);
        if (fd == -1) return;

        // 设置共享内存大小
        if (ftruncate(fd, m_size) == -1) {
            close(fd);
            return;
        }

        void* ptr = mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        if (ptr == MAP_FAILED) {
            close(fd);
            return;
        }

        m_handle = reinterpret_cast<void*>(static_cast<intptr_t>(fd));
        m_ptr = ptr;
#endif
    }

    void close() {
        if (m_ptr) {
#ifdef _WIN32
            UnmapViewOfFile(m_ptr);
            CloseHandle(static_cast<HANDLE>(m_handle));
#else
            munmap(m_ptr, m_size);
            int fd = static_cast<int>(reinterpret_cast<intptr_t>(m_handle));
            close(fd);
            shm_unlink(m_name.c_str()); // 可选:删除共享内存对象
#endif
            m_ptr = nullptr;
            m_handle = nullptr;
        }
    }

private:
    std::string m_name;
    size_t m_size;
    void* m_handle;
    void* m_ptr;
};

使用示例

两个进程可以使用相同的名称访问同一块共享内存。

刺鸟创客 刺鸟创客

一款专业高效稳定的AI内容创作平台

刺鸟创客 110 查看详情 刺鸟创客
int main() {
    SharedMemory shm("my_shared_memory", 4096);

    if (!shm.is_valid()) {
        // 处理错误
        return 1;
    }

    // 写入数据
    char* data = static_cast<char*>(shm.data());
    std::strcpy(data, "Hello from process!");

    // 其他进程可读取该数据
    return 0;
}

注意事项与建议

  • 共享内存不提供同步机制,需配合互斥锁(如命名信号量或mutex)防止竞态条件。
  • 命名冲突:确保共享内存名称在系统范围内唯一,建议加前缀或UUID。
  • 资源清理:进程异常退出可能导致共享内存残留,应确保调用shm_unlink或关闭句柄。
  • 权限设置:POSIX共享内存注意shm_open的mode参数,避免权限不足。
  • 性能:内存映射适合大块数据共享,小数据可考虑管道或消息队列。

更高级选择:Boost.Interprocess

若项目允许使用第三方库,Boost.Interprocess 提供了完整的跨平台共享内存封装,极大简化开发。

示例:

```cpp #include #include

using namespace boost::interprocess;

shared_memory_object shm(create_only, "my_shm", read_write); shm.truncate(1024); mapped_region region(shm, read_write); std::strcpy(static_cast(region.get_address()), "Hi");


<p>Boost方案自动处理平台差异,支持同步原语,是生产环境推荐做法。</p>

基本上就这些。手动实现可用内存映射,追求稳定和效率建议上Boost。

以上就是c++++怎么创建一个跨平台的共享内存区域_C++中跨进程共享内存的实现方式的详细内容,更多请关注其它相关文章!


# 推荐使用  # 直通车关键词排名很低  # 东莞seo广告如何推广  # 新媒体营销推广详案模板  # 深圳网站建设免费  # 实体店营销如何推广自己  # 安阳整合营销推广怎么样  # 刷评论网站推广QQ  # 越秀互联网口碑营销推广  # 淘宝网的网站推广营销  # 外推seo  # 库中  # 游戏开发  # 如何实现  # 重写  # 数据结构  # c++  # 多个  # 创建一个  # 如何使用  # 同步机制  # win  # unix  # ai  # access  # app  # 操作系统  # windows  # word  # linux  # 共享内存 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 蛙漫限时开放最深处链接_蛙漫全站漫画会员同款秒开地址  Win11怎么开启省电模式_Win11电池节电模式自动开启  Golang如何使用const iota_Go iota常量计数器讲解  J*aScript map 迭代中检测空数组元素的有效方法  如何使用Rector自动化升级旧代码_通过Composer安装和配置Rector进行代码重构  抖音网页版怎么|直播|_抖音网页版开播操作指南  J*aScript设计模式实践_j*ascript代码优化  解决Django多数据库/多Schema环境下外键迁移问题  excel怎么制作工资条 excel快速生成工资条的方法  Promise错误处理:在catch后终止链式then执行的策略  win11如何加载ICC颜色配置文件 Win11校色文件安装与显示器色彩管理【指南】  单射、满射与双射的关系 一文理清所有逻辑  必由学官网首页入口 必由学教师网页版登录指南  微博网页版官方账号登录 微博网页版内容浏览使用指南  Golang如何实现容器化日志收集与分析_Golang容器日志收集分析方法  JUnit5/Mockito:优雅测试内部依赖与异常处理的实践  黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】  小红书网页版入口链接分享 小红书官网直接进  lar*el怎么安全地存储和获取配置文件中的敏感信息_lar*el敏感信息安全存储方法  铁路12306卧铺选择攻略 铁路12306下铺座位预定技巧  C++如何操作注册表_Windows平台下C++读写注册表的API函数详解  css元素hover动画延迟生效怎么办_使用animation-delay调整触发时间  晋江读书网页版在线登录 晋江读书电脑版官网  Win11蓝牙耳机断连怎么解决 Win11蓝牙设置重新配对与驱动更新【技巧】  优化 Python 函数中的条件逻辑:解决 if-else 嵌套与参数选择问题  Spyder启动失败:字体文件权限拒绝错误解决方案  俄罗斯Yandex搜索引擎入口_Yandex官网免登录一键访问  AO3最新入口2025公告_AO3中文官网合集  NVIDIA股价11月重挫12%:下月有望好转 但难回5万亿美元巅峰  Golang如何使用new_Go new分配内存机制讲解  《刺客信条4:黑旗》重制版新细节曝光:无缝加载 地图更细致!  Win11怎么安装Linux子系统 Win11 WSL2安装Ubuntu及环境配置指南  CSS自定义字体样式被系统字体替换怎么办_font-face方式指定font-display控制渲染策略  如何仅使用CSS更改登录界面背景图像图标的颜色  age动漫网站入口 age动漫官网直接访问入口  PHP中SSG-WSG API的AES加密实践:正确使用初始化向量  在J*a中如何捕获IndexOutOfBoundsException_索引越界异常防护方法说明  QQ邮箱网页版邮箱入口 QQ邮箱官方登录平台  探索高级语言到原生C/C++的转译:挑战与内存管理策略  mc.js免安装版 mc.js一键畅玩入口  小米Civi 4录制视频过暗_小米Civi 4亮度优化  WordPress插件开发:正确注册卸载钩子与避免常见陷阱  Angular响应式表单:实现提交后表单及按钮的禁用与只读化  Lar*el DB::listen 事件中的查询执行时间单位解析  可靠CSGO开箱平台解析 CSGO开箱网合集  C++如何实现线程池_C++11手动实现一个简单的固定大小线程池  微信客户端如何收红包_微信客户端接收红包使用教程  海量存储:机器视觉智能化的核心基石  处理动态列数据:J*a ArrayList的正确初始化与字符累加教程  漫蛙漫画网页端入口 漫蛙2官方正版漫画站点 

搜索