【进程间通信(三)】共享内存(system v)

一.共享内存通信的实现原理

其实进程之间通信的本质就是让通信双方看见同一份内存。这样当这份内存的数据发生改变的时候,双方进程都能直接观察到结果。这份内存存放在共享数据区,由操作系统提供并维护。共享内存的特性是只会储存进程之间通信产生的临时变量,而不会刷新到磁盘。不过这里有个问题就是,两个进程如何保证找到的共享内存是同一块内存呢。进程之通过key值实现这一点的,key值是由系统路径和你指定的一个id计算而成,当你提供相同的路径和id的时候算出的key值是完全一样的。而共享内存的申请需要key值参与,这样进程就可以拿着key值去找key值相符的共享内存了。注意共享内存不仅仅指的是内存数据块,他同时还包括共享内存的内核数据结构。

二.如何使用共享内存 

(1).创建共享内存:创建共享内存有两步,首先计算出key值,在通过key值申请出共享内存

计算key值:使用ftok这个函数

pathname: 系统路径
shmaddr:指定连接的地址
proj_id:指定id
返回值:成功返回一个key值,失败返回-1

申请共享内存:使用shmget这个函数

key:这个共享内存段名字(上文的key值)
size:共享内存大小
shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的,这里有两个标志码,IPC_CREAT和IPC_EXECL,前者的作用是创建共享内存,若当前key值的共享内存已经存在,就使用旧的共享内存,后者必须和前者一起组合使用,组合效果确保了每次申请的共享内存都是全新的。
返回值:成功返回一个非负整数,即该共享内存段的标识码(shmid);失败返回-1

 

(2)挂接共享内存:刚刚创建出来的共享内存是无法直接使用的。因为还没有和当前进程建立起联系。shmat是挂接进程,shmdt是解除挂接

shmat:

shmid: 共享内存标识
shmaddr:指定连接的地址
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回一个指针,指向共享内存第一个节;失败返回-1

shmdt:

int shmdt(const void *shmaddr);
参数
shmaddr: 由shmat所返回的指针
返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段
(3)到这步就可以正常使用共享内存了,我们已经通过shmat拿到了共享内存的指针,我们可以把这一块内存当成一个大字符串来使用。

(4)接触挂接并删除共享内存:

上文当中已经说过解除挂接的函数,删除共享内存

 shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作(有三个可取值)
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1

使用时注意一点,共享内存的生命周期不由进程决定,也就是说除非你手动删除,否则一旦创建,一直存在,除非你重启。

三.案例演示

模拟客户输入服务器输出

下图为服务器端

下图为客户端

 

二.共享内存通信的优势和缺点

优势:使用共享内存的通信方式是最快的。因为它本身是内存级别的读和写。并且没有过多的拷贝。通常我们使用管道通信至少要经历四次拷贝,第一次拷贝到用户输入缓冲区,第二次拷贝到管道文件,第三次拷贝到输出缓冲区,第四次拷贝出来打印。极大的降低了效率。

劣势:共享内存因为直接能看到,没有进程控制,当遭遇多个执行流互相运行访问临界资源的时候可能会造成干扰。可以通过手动添加进程控制保证原子性解决

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值