Linux共享内存

system V 共享内存

进程间通信的本质就是让不同的进程看到同一个空间

直接原理

操作系统在物理内存处开辟一段空间, 在修改页表将这段空间映射到一个进程的共享区, 然后将对应的虚拟地址的起始地址显示给应用层, 对另外一个进程也做同样的操作, 这样两个进程就可以通过页表访问这一段内存了。
在这里插入图片描述
而如果我们要释放共享内存:那么就有操作系统先释放共享内存, 再去关联

上面的这些操作都是有操作系统去直接做的

在这里插入图片描述

直接写一部分代码, 测试一下对应的功能

创建共享内存

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

你怎么保证让不同的进程看到的是同一个共享内存?
你怎么知道这个共享内存是存在还是不存在?

这就靠的是我们的第一个参数key(共享内存标识符)

谈谈key:
1 key是一个数字, 他是几不重要, 关键在于他必须在内核中具有唯一性, 能够让不同的进程进行唯一性标识。
2 第一个进程可以通过key创建共享内存, 第二个之后的进程, 只要拿到同一个key就可以和第一个进程看到同一个共享内存了。
3 对于一个已经创建好的共享内存, key在哪? 在共享内存的描述对象中!
4 第一次创建的时候, 必须有一个key, 这个key怎么来?
5 key跟路径一样是具有唯一性

在这里插入图片描述

第一个参数是路径, 第二个参数是项目id
在这里插入图片描述
在这里插入图片描述
当我们测试的时候, 发现第一次key和shmid都成功了, 但是第二次的时候key成功了但是shmid却失败了, 这是为什么呢?

在这里插入图片描述
我们通过查看系统内共享内存发现, 原来是我们之前创建的共享内存没有被释放导致的

所以我们得知共享内存的生命周期是随内核的!用户不主动关闭, 共享内存会一直存在。

我们看上面的那个图, 其中perms代表的是该共享内存的权限, nattch代表的是有多少个进程和这个共享内存关联。

我们如何设置共享内存的权限呢?
在这里插入图片描述
直接在最后一个参数中带上权限即可

现在我们成功的创建了共享内存, 但是如何用另外一个进程获取这个共享内存呢?

在这里插入图片描述
我们像这样就实现了一个接口是创建内存, 一个接口是获取内存。

关于共享内存的大小, 我们做一下补充的说明
在这里插入图片描述

现在我们能获取共享内存的shmid了, 如何将我们的进程与这个共享内存挂接起来呢?
在这里插入图片描述
shmid就不用解释了
shmaddr表示的是, 我们想把共享内存挂接到进程的那个地址里去? 如果不想自己设置就传NULL让系统自己去决定, 最后具体挂接到哪个位置会由该调用的返回值void*返回给我们。
shmflg我们不去了解, 他表示是我们去挂接他的权限, 我们直接传0表示就默认用共享内存的权限即可。

如果我们像去关联的话可以使用shmdt
在这里插入图片描述
我们只需要传入共享内存挂接的地址即可去关联

其中返回值 成功返回0 失败返回-1

我们创建了共享内存, 自然也需要去释放他, 所以还有一个接口叫做shmctl

在这里插入图片描述
第一个参数不用解释

cmd表明我们要做什么操作
在这里插入图片描述
这是他的一些选项, 我们现在要关注的就是这个IPC_RMID, 因为这个选项就是用于删除共享内存的
buf
在这里插入图片描述
shmid_ds 是一个类似于操作系统中管理共享内存的结构体

由于我们现在只是需要删除共享内存, 所以我们不关注他的属性, 直接传NULL即可
在这里插入图片描述
成功就返回0, 失败就返回-1

在这里插入图片描述
在这里插入图片描述
我们来运行一下上述的代码。

在这里插入图片描述

首先, 我们发现, 我们直接运行用户端, 发现用户端没有等客户端输入消息, 直接就开始读取, 所以读到的是空

在这里插入图片描述
在这里插入图片描述
我们运行客户端, 写入一段消息, 成功的被用户端读取到了

在这里插入图片描述
事实上, 我们是不需要自己定义缓冲区的, 因为共享内存本身就是一个空间, 所以我们直接往里面输入数据即可。

一旦有共享内存挂接到了自己的地址空间中, 我们直接把他当做自己的空间来用就可以了, 不需要使用系统调用

共享内存的特征, 扩展代码

  1. 共享内存没有同步互斥之类的保护机制
  2. 共享内存是所有的进程中速度最快的!(拷贝操作进行的少)
  3. 共享内存内部的数据, 由用户自己维护

共享内存的属性

在这里插入图片描述
shmid_ds 从上到下:

  • 共享内存的权限
  • 共享内存的大小
  • 最后一次挂接时间
  • 最后一次去关联时间
  • 最后一次改变的时间
  • 谁创建的这个共享内存(靠pid标识)
  • 谁最后关联/去关联(靠pid标识)
  • 当前有多少的进程与该共享内存挂接

我们仔细观察可以发现第一个变量的类型是一个结构体, 这个结构体的结构在我们图下方
ipc_perm

  • __key 这个就是我们提供给shmget的那个key
  • mode 表示共享内存的权限
    在这里插入图片描述
    我们通过shmctl的IPC_STAT选项来获取共享内存的shmid_ds,

在这里插入图片描述
在这里插入图片描述

用管道维护共享内存的同步机制

在客户端以写方式打开管道文件
在这里插入图片描述
当我们在写入后, 我们就象征性的写点内容进管道文件里
在这里插入图片描述
在用户端用读方式打开管道文件
在这里插入图片描述
是的用户在读到管道文件里的字符后再去读共享内存里的内容
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值