c++ fork 进程时 共享内存_DeltaCV之共享内存篇

我的原文:

https://www.dasuda.top/index.php/2020/05/11/deltacvzhigongxiangneicunpian/​www.dasuda.top

Github地址:

DasudaRunner/DeltaCV​github.com
a181e400dd68f1f3714c0d3d843af47f.png

这篇文章我们来认识一下线程间通信的一种手段—共享内存,共享内存由于其特殊性—共享内存是存在与每个进程的地址空间中的,通俗点就是这部分数据是对每个进程可见的,这样每个进程都可以在一定条件下直接操作共享内存中的数据,避免了数据的复制等耗时的操作,这也是共享内存比其他几种IPC机制(信号量、管道、消息队列等)的通信方式效率高的原因,但是共享内存也有缺点,那就是需要独立实现消息的同步机制。 本文将完成一个基础的共享内存类模板,包含在DeltaCV项目中,欢迎star,fork。

概述

在boost/Interprocess中,提供了很多关于操作系统底层的进程间通信的抽象层,它使用C++将操作系统的底层接口进行封装,并消除了不同操作系统之间各种各样的接口带来的开发困难等问题。

共享内存

先介绍一种最普通的共享内存创建方式,boost::interprocess::shared_memory_object类。

#include 

共享内存创建后大小为0,我们使用truncate()方法来为共享内存设定大小,单位为字节。

// 为刚才创建的共享内存开辟1024个字节大小的空间。

然而刚才我们创建的共享内存虽然对所有进程可见,但是现在还不能直接操作,因为每个进程都有自己独立的地址空间,我们还需要将上面的共享内存映射进当前进程的地址空间中,可以使用mapped_region()方法完成。

#include 

接下来就是开始向共享内存中存数据了,跟我们普通的指针操作一样.

// 先将地址的指针强制转换成int指针,因为我们要储存的是int变量

那如何删除我们创建的共享内存呢?多数linux系统中,如果不主动删除共享内存,它会一直存在到系统重启.

//返回值指示了是否删除成功

托管共享内存

然而上述的方式几乎不会用到,因为它每次需要按单个字符的形式读写内存,所以绝大多数情况下我们会使用托管共享内存方式,它会以内存申请的方式对共享内存对象进行初始化.

#include 

删除托管共享内存

boost

互斥对象

既然共享内存对所有进程都可见,那么怎么保证共享内存的读写不会相互干扰呢?那就是使用互斥对象,当共享内存被使用时,互斥对象被占用,其他进程想要操作同一共享内存时,就需要等待互斥对象释放,这样就保证了共享内存的正确读写,类似于多线程中的锁.

互斥对象的声明

#include 

DeltaCV中的共享内存类模板

至此,关于boost下的共享内存编程就简单的介绍一下,应该能满足日常的使用了,下面我将介绍我在DeltaCV中封装的共享内存类模板,整体框架类似与ROS中的topic形式,提供发布者和订阅者.完整代码见DeltaCV.

发布器

template 

订阅器

template 

小技巧

代码中,我额外添加了一个标志位update_flag,用来指示当前取到的数据是否是最新值,因为只要发布器那边存入一次数据,update_flag这个变量就置为1,而订阅器每取一次数据,就讲update_flag置0,所以当订阅器的获取频率超过发布器时,订阅器取到的数据一部分是未更新的数据,则订阅器能通过get()的返回值来选择是否使用本次获取的数据(若返回值为true,则为最新值,若为false,则说明自上次订阅器取过值后到这次取值之间,发布器没有存入过新的数据).

演示

分别新建两个main函数,代表两个进程,其中一个作为发布器,每5s发布一次数据,另外一个作为订阅器,每1s获取一次数据.

// main1.cpp

最终输出为:(可以看到5s内,订阅器有4次获取的是未更新的值)

update: 1 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 1 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 1 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5
update: 0 ,a[0]: 4 ,a[1]: 5

参考文献:http://zh.highscore.de/cpp/boost/interprocesscommunication.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值