当前位置: 首页 > article >正文

【深入学习Linux】System V共享内存

目录

前言

一、共享内存是什么?

共享内存实现原理

共享内存细节理解

二、接口认识

1.shmget函数——申请共享内存

 2.ftok函数——生成key值

再次理解ftok和shmget

1)key与shmid的区别与联系

2)再理解key

3)通过指令查看/释放系统中的ipc资源

3.shmctl函数——控制、释放共享内存

struct shmid_ds是什么

4.shmat函数和shmdt函数——对共享内存进行关联和去关联

三、共享内存的优缺点分析

总结



前言

早在设计Unix时,系统开发者就发现了一个悖论:在某些情况下,系统中的进程既要满足互相隔离又要彼此协同合作。

由此衍生出了System V IPC等通信方式,在保持进程独立性的前提下,通过内核中介、权限控制和同步机制实现安全通信。

System V IPC通信机制主要包括:消息队列/ 信号量/ 共享内存三种通信方式,本文主要讨论共享内存的概念原理以及使用方式。


一、共享内存是什么?

先来看看共享内存的概念:

通过让不同的进程看到同一块内存的方式,就被称为“共享内存”

在对共享内存的概念有了一定了解后,再来理解共享内存的原理。

共享内存实现原理

在不破坏进程独立性的前提下让两个进程通信,操作系统通过引入能让两个进程都能看到的同一份“资源”实现。对于共享内存,这份资源就是物理内存上的一段内存块。

以下阐述共享内存的原理。

共享内存细节理解

1)C/C++语言中的malloc等申请空间的函数能用于申请共享内存吗?

不能,malloc等函数申请的空间只属于该进程自己,不能被其他进程共享。共享内存机制是专门设计出来用于IPC进程间通信的。

2)共享内存是一种通信方式,想要通信的进程都可以使用。当两个进程希望进行通信时,可以使用已有的正在被其他进程使用的共享内存通信,也可以额外申请一块内存用于通信,根据实际需求决定。

3)系统中可能同时存在很多共享内存块。

二、接口认识

1.shmget函数——申请共享内存

 

2.ftok函数——生成key值

再次理解ftok和shmget

1)key与shmid的区别与联系

ftok函数返回值是key,shmget的返回值是shmid(共享内存标识符)。key与shmid的关系,有些类似于文件描述符fd与inode的关系,一个是应用进程层面使用的(shmid与fd),另一个是系统内核层面使用的(key与inode)。

2)再理解key

3)通过指令查看/释放系统中的ipc资源

删除共享内存指令:

 shmid可以通过上述ipcs指令查看。

3.shmctl函数——控制、释放共享内存

struct shmid_ds是什么

在shmctl函数的第三个参数中出现了struct shmid_ds结构体,该结构体是操作系统暴露给用户级的一种数据结构,他与操作系统为方便管理共享内存创建的数据结构再内容上高度类似(系统中的还要更为复杂)。

struct shmid_ds其中记录了该共享内存的属性,包括现在有哪些进程正在通过该共享内存通信的信息,以及key值等。

若想获取共享内存的属性参数,可以通过创建一个空的struct shmid_ds对象,再将地址传入shmctl函数中。注意此时的comd参数需传入IPC_STAT。

struct shmid_ds tmp;
shmctl(shmid,IPC_STAT,&tmp);

4.shmat函数和shmdt函数——对共享内存进行关联和去关联

注意:正确的释放共享内存的流程应该是,先将进程与共享内存去关联,然后再释放共享内存

这里附上笔者总结的共享内存创建流程:

在申请共享内存时应做到,谁申请,谁释放。

三、共享内存的优缺点分析

1.优点

共享内存在所有进程通信间,通信速度是最快的——能减少的拷贝次数。

何以见得共享内存能减少拷贝次数?

假如同样的代码和数据,综合考虑管道和共享内存分别进行通信,在考虑上键盘输入,和显示器输出后,共享内存有几次拷贝数据,管道呢?

由上图我们可以清楚的观察到,相比管道,共享内存不用在buffer缓冲区中临时中转一下,由此能够减少一定的数据拷贝。

2.缺点

共享内存在数据通信时,没有对数据做任何保护——没有同步、互斥机制。

甚至管道可能出现写端还未写完数据,而读端就来读取的情况——这时读端大概率读到无意义的数据。

比如,管道通信写端在没有写入数据时,读端会被OS阻塞,反之亦然;

管道在读端将数据读取后,写端再写会覆盖已读的数据。

是否能在不使用信号量的前提下,对共享内存进行保护?

可以给通信的进程双方添加管道,凡共享内存通信前先借助管道确认对方是否准备完毕。

读/写端先不直接访问共享内存,而是先通过管道通信确认后,再通过共享内存通信。

比如,读端想要通过共享内存读取数据之前,先在管道读端处读取信号(如一个特定字符)。若未读取到特定值字符,则由于管道的特性读端进程会被阻塞,直到写端发来信号。


总结

本文详细介绍了System V通信方式中的“共享内存”通信方式。从原理的介绍,到接口的使用,再到最后的优缺点分析,较为系统的剖析共享内存的原理和使用。

虽然共享内存在如今这个万物互联的世界越来越不常用,但在某些脱网单机情况下依旧是进程通信的最佳选择。

希望本文对你有所帮助。

读完点赞,手留余香~

http://www.lryc.cn/news/2404968.html

相关文章:

  • 编程基础:执行流
  • 理解非结构化文档:将 Reducto 解析与 Elasticsearch 结合使用
  • 算法训练第十天
  • 2种官方方法关闭Windows防火墙
  • [面试精选] 0094. 二叉树的中序遍历
  • 股指期货期权交易规则是什么?
  • 学习笔记(23): 机器学习之数据预处理Pandas和转换成张量格式[1]
  • 2025年6月6日第一轮
  • 记一次运行spark报错
  • 12-Oracle 23ai Vector 使用ONNX模型生成向量嵌入
  • 2. 库的操作
  • pytorch 与 张量的处理
  • layer norm和 rms norm 对比
  • Java高级 | 【实验六】Springboot文件上传和下载
  • RKNN开发环境搭建1-基于Ubuntu 18.04系统使用Docker安装rknn-toolkit2
  • qt使用笔记二:main.cpp详解
  • VBA进度条ProgressForm1
  • 行为型设计模式之Interpreter(解释器)
  • 深入解析 CAS 操作
  • vue3+TS+eslint9配置
  • 【bug】Error: /undefinedfilename in (/tmp/ocrmypdf.io.9xfn1e3b/origin.pdf)
  • HarmonyOS5.0——CodeGenie:鸿蒙生态的AI编程革命​
  • 【Dv3Admin】系统视图字典管理API文件解析
  • 免费 SecureCRT8.3下载、安装、注册、使用与设置
  • Redis :String类型
  • 两种Https正向代理的实现原理
  • 第18节 Node.js Web 模块
  • 网络爬虫一课一得
  • LeetCode--24.两两交换链表中的结点
  • 嵌入式SDK技术EasyRTC音视频实时通话助力即时通信社交/教育等多场景创新应用