Linux:SystemV通信
目录
一、System V通信
二、共享内存
代码板块
总结
三、信号量
信号量理论
信号量接口
一、System V通信
System V IPC(inter-process communication),是一种进程间通信方式。其实现的方法有共享内存、消息队列、信号量这三种机制。
二、共享内存
进程间通信的本质就是让不同进程看到同一份资源,比如匿名管道是利用了父子进程之间继承机制,命名管道是利用路径找到同一个文件。
共享内存本质也是让不同进程看到同一份资源。
学习进程的通信方法,本质都是在学习是如何让不同进程使用到同一份资源的。
- 共享内存机制

第一步,由操作系统在内存中开辟内存空间。

第二步:操作系统把共享内存的地址通过页表映射到进程地址空间中。

另一个进程同样如此。

进程通过这块内存通信,通信完毕后,还有移除映射、释放共享内存等步骤。
- 共享内存的细节
实际上,会有多个进程都采用共享内存的方式通信,因此会有多个被开辟的小内存空间,用来通信,操作系统同样要对这些个共享内存作管理,同样要标识唯一的共享内存,这个关键字在Linux下的类型命名为key_t。
于是,我们要理解共享内存的本质,就是要理解,两个进程究竟是通过怎样的方式拿到同一个key_t的。
先来认识一下,Linux下创建共享内存的系统调用接口。
man 2 shmget

第一个参数,key_t key ,这个参数就是用来标识唯一的共享内存空间的,由用户传入,并不是由操作系统指定。
原因:当一个进程想要和另一个进程通信,A进程是无法得知B进程的一切信息的,它只能自己申请创建一块共享内存空间,然后想办法让B进程也能访问到这个特定的内存空间,但是在操作系统看来,它管理这多个这样的内存空间,操作系统是不知道A和B是想要通信的,也就无法将这个唯一标识传给B进程。
因此这个参数key只能由用户设置。
但是,直接设置这样一个标识符可能会大概率和其他共享内存空间的标识符冲突,因此有专门的一个函数,可以根据用户设置的字符串来生成唯一且随机的一个标识符。
man 3 ftok

想要通信的两个进程,到时候在源代码中约定一样的字符串,根据这个函数生成共享内存空间的唯一标识符,由其中一个进程向操作系统申请创建这块内存空间,至此,两个进程都能拿到同一块共享内存空间了,这便是System V共享内存的实质。
第二个参数,指定共享内存空间的大小
第三个参数,用来指定特殊标志,传参选项有IPC_CREAT、IPC_EXCL,

传参形式有三种:
只传IPC_CREAT:如果要创建的共享内存空间不存在,就创建它,如果已经存在,则直接使用它。
只传IPC_EXCL:无意义。
传参IPC_CREAT | IPC_EXCL: 如果要创建的共享内存空间不存在,就创建它,如果已经存在,则报错!!
代码板块
- 1.先实现获取key
//可以随机定义
const char* pathname = "/home/utocoo/Desktop/linux/241221";
const int pri_id = 0x67;
//获取key
key_t CreatKeyOrDie()
{key_t key = ftok(pathname,pri_id);if(key < 0){cerr << "ftok error,errno->" << errno<<"->" << strerror(errno) << endl;exit(1);}return key;
}
- 2.再根据key申请共享内存
//根据Key申请共享内存
int CreatShmOrDie(key_t key,size_t size,int flag)
{int shmid = shmget(key,size,flag);if(shmid < 0){cerr << "shmget error,errno->" << errno << "->" << strerror(errno) << endl;exit(2);}return shmid;
}
然而,在通信的用户看来,创建共享内存时,只需要指定key和内存大小即可,所有可以把这个函数再次封装。
并且对于要创建内存的进程而言,比如A进程,创建内存时,如果不存在就创建,如果存在则报错;而对B进程而言,如果内存已经存在,只需要获取它的shmid即可。
//A进程创建
int CreatShm(key_t key,size_t size)
{CreatShmOrDie(key,size,IPC_CREAT | IPC_EXCL | 0666);
}
//B进程不用再创建,只需要获取即可
int GetShm(key_t key,size_t size)
{CreatShmOrDie(key,size,IPC_CREAT);
}
再来认识一下创建共享内存空间函数shmget的返回值,int shmid,这个返回值同样可以标识唯一的一块内存空间,它和另一个标识符key又有什么样的关联?
key这个关键字,是在内核级别,帮助操作系统标识唯一的共享内存空间。
而shmget的返回值,是帮助用户来管理这块内存空间,作为用户来讲,往往是通过shmid来使用各种各样的接口。
- 释放共享内存空间
进程退出后,如果用户不主动释放申请的共享内存,那么这块内存的生命周期是一直跟随着操作系统的,只有重启才会重新初始化这块内存。
释放共享内存的接口为shmctl+特定参数
man 2 shmctl

第三个参数的类型就是操作系统用来描述共享内存的结构体,cmd的取值范围在man手册中也有说明。
//释放共享内存
void DeleteShm(int shmid)
{int r = shmctl(shmid,IPC_RMID,nullptr);if(r < 0){cerr << "delete shm error,errno->" << errno << "->" << strerror(errno) << endl;exit(3);}else {cout << "delete shm->" << shmid << "success" << endl;}
}
关于释放共享内存,上面介绍的是在代码中我们利用系统调用接口实现,也可以在命令行中通过指令完成释放。
ipcs指令查看SystemV通信的所有介质。
ipcs

ipcs -m则只查看所有的共享内存。
ipcs -m

ipcrm -m 指定的shmid则在命令行中删除指定shmid的共享内存。
ipcrm -m shmid

- 将内存空间挂载或者说映射到进程的虚拟地址空间中
所用到的接口是shmat,

第二个参数,shmaddr用来指定要将指定shmid的共享内存映射到虚拟地址空间的哪个地方,第三个参数shmflag默认传0即可,特殊用途可以传特殊参数,这些在man手册中均有说明。
需要说明的是返回值

shmat会返回虚拟地址空间段地址,否则返回(void*)-1
//映射到进程上面
void* ShmAttah(int shmid)
{char* addr = (char*)shmat(shmid,nullptr,0);if((int64_t)addr == -1){cerr << "ShmAttach error,errno->" << errno << "->" << strerror(errno) << endl;return nullptr;}return addr;
}
- 既然有挂载,也就应该有取消挂载
相应的接口为shmdt,dt是detach的缩写,

总结
共享内存的特征:由于共享内存,当写进程不再向内存中写数据的时候,读进程还是会一直从内存中读数据,共享内存并不提供进程间通信的同步机制,这一点不同于管道通信,这是它的缺点。
然而,正因为共享内存的缘故,当写进程向内存中写完数据后,读进程可以立马从内存中读取到数据,这个过程又不同于管道通信,因为管道通信是不断的拷贝,因此,共享内存的通信方式却是最快的通信方式,这是它的优点。
因为共享内存块注定这种通信方法无法提供通信同步机制,因此,可以在共享内存通信的基础上,提供一个管道,利用管道来同步、利用共享内存来通信。
三、信号量
信号量理论
- 同步和互斥。
互斥机制:像共享内存这样的通信方式中,写进程在写的过程中,如果读进程可以随时随地的读,最终可能造成数据不一致的情况,因此,为了避免这种数据不一致的情况,引入互斥机制,让一份资源只能由一个进程在享用,另一个进程想要享用,必须要排队等待。
同步机制:引入互斥机制后,个别进程可能长时间享用一份资源,导致其他进程在一段时间内都无法享用该资源,因此,引入同步机制,来解决个别进程长时间占用资源的问题。
- 临界资源
被保护的资源,进程之间互斥访问的资源,称为临界资源。
用来访问临界资源的代码,被称为临界区,同时,其他代码被称为非临界区,而保护公共资源是互斥访问本质就是在保护临界区,显然,如何保护临界区,是由程序员来实现。
- 什么是操作的原子性
对临界资源的操作,只有两种状态,要么还没开始访问,要么已经结束访问。
- 临界资源的访问
将临界资源,也就是一块内存,视为一个整体,这个时候一个进程访问,其他进程必须等待,考虑到效率问题,将这块内存划分为多个小内存,比如100MB的共享内存划分为多个4KB的小内存,让多进程互斥的访问小内存,可以提高效率。
这种设计需要满足:
1.被划分的小内存数量是有限的,因此,必须限制多进程数量,只允许一定数量的进程访问。
2.如何合理分配小内存给多个进程。
- 什么是信号量
“信号量”往往是在说信号量机制,我们已经知道信号量机制是SystemV通信方式的一种,是用来帮助进程通信的,那么要如何理解。
信号量本质是一个计数器,用来表述临界资源的数量,计数器有加减操作来表示临界资源数量的变化,某一个进程对这个计数器可能做加或者减操作,造成计数器值的改变要求其他进程也能看到,符合“让不同的进程看到同一份资源”这一原理,因此,信号量资源本质也是共享资源。
- 信号量不能用整型变量表示
一是因为整型变量不能被共享,二是因为整型变量的加减操作不满足原子性。
- 信号量机制
进程在访问临界资源的时候,
通常是先要申请资源,信号量做减法,也称P操作。
申请成功则表示对资源的预订,不一定立刻访问,申请失败表示资源数不够,进程必须等待
资源访问完毕后进程释放资源,信号量做加法,也称V操作。
PV操作就是进程在保护临界资源的过程。
- 信号量本身就是临界资源
信号量本身就是临界资源,必须要有申请、释放信号量的过程。
信号量接口
- 申请信号量
semget。
- 释放信号量
semctl。
- PV操作
semop
相关文章:
Linux:SystemV通信
目录 一、System V通信 二、共享内存 代码板块 总结 三、信号量 信号量理论 信号量接口 一、System V通信 System V IPC(inter-process communication),是一种进程间通信方式。其实现的方法有共享内存、消息队列、信号量这三种机制。 …...
C#上位机通过CAN总线发送bin文件
让gpt生成一段代码用来把bin文件通过can总线发出去 c#代码还是比较强大的,各种功能基本都是一两行代码就实现了,这里记录一下对这个代码的理解和解读 主要代码如下,传入bin文件的地址即可将其从指定的can通道发送出去: public …...
CV 图像处理基础笔记大全(超全版哦~)!!!
一、图像的数字化表示 像素 数字图像由众多像素组成,是图像的基本构成单位。在灰度图像中,一个像素用一个数值表示其亮度,通常 8 位存储,取值范围 0 - 255,0 为纯黑,255 为纯白。例如,一幅简单的…...
2-Kbengine+Unity3D多人在线游戏DEMO源码架构分析
2-Kbengine+Unity3D多人在线游戏DEMO源码架构分析 目录 一、服务器端 1、编写并生成我们的服务器端和客户端通用的游戏协议 2、 认识Entity实体 3、 官方DEMO-kbengine_demos_assets分析 二、 客户端...
Vue.js组件开发-如何实现表头搜索
在Vue.js组件开发中,实现表头搜索通常涉及在表格组件的表头添加输入框,并让用户能够输入搜索关键字来过滤表格数据。 以下是一个使用Element UI的el-table组件实现表头搜索的示例: 一、准备阶段 确保Element UI已安装: 确保…...
lerna使用指南
lerna版本 以下所有配置命令都是基于v8.1.9,lerna v5 v7版本差别较大,在使用时,注意自身的lerna版本。 lerna开启缓存及缓存配置 nx缓存是v5版本以后才有的,小于该版本的无法使用该功能。 初始化配置 缓存配置文件nx.json&am…...
spark,读取和写入同一张表问题
读取a表,写入a表 1.写入的是分区表,不报错 2.读取上来之后,创建为临时视图temp,然后先写入a表,再使用temp,就会报错 解决办法:可以先使用temp,再写入a表 3.写入的不是分区表&…...
iOS - TLS(线程本地存储)
从源码中,详细总结 TLS (Thread Local Storage) 的实现: 1. TLS 基本结构 // TLS 的基本结构 struct tls_data {pthread_key_t key; // 线程本地存储的键void (*destructor)(void *); // 清理函数 };// 自动释放池的 TLS class Autorelease…...
node.js项目依赖关系分析工具 Depazer 的使用
node.js项目依赖关系分析工具 Depazer 的使用 Depazer 是一个用于 分析和可视化 Node.js 项目依赖关系 的工具。它可以帮助开发者快速了解项目的依赖结构、模块关系,以及可能存在的问题,从而优化代码架构和依赖管理。 功能特点 依赖关系分析࿱…...
QT 如何禁止QComboBox鼠标滚轮
一般情况下,QComboBox会相应鼠标的滚轮事件,即当鼠标停靠在QComboBox上方时,滚动鼠标滚轮,QComboBox的选项会发生切换。但这或许并不是我们希望所出现的,尤其是当QComboBox嵌入在QScrollArea中时,用户只是想…...
理解CPU负载与使用率
目录 CPU使用率 CPU负载 CPU使用率 定义:就像看一个工人干活的时间占他上班时间的比例。比如工人上班8小时,实际干活6小时,干活时间占比就是68100%75%。对于CPU,单核的看它被占用的时间占总时间的比例,多核的就把每个…...
浅谈计算机网络01 | SDN数据平面
浅谈基本云架构 一、计算机网络数据平面的基础理论1.1 数据平面与控制平面的区分1.1.1 两者功能差异1.1.2 协同工作机制 1.2 数据平面在网络架构中的位置与角色1.2.1 与各网络层次的关系1.2.2 对网络整体性能的影响 二、数据平面的关键技术原理2.1 转发技术2.1.1 基于目的地转发…...
《Java开发手册》核心内容
文章目录 引言I 编程规约II 异常日志III 单元测试 :IV 安全规约 :V MySQL数据库:VI 工程结构 :VII 设计规约 :引言 手册的愿景是提升代码质量和开发效率,通过规范化的编码实践来减少错误和提高系统的稳定性。 I 编程规约 命名风格:规定了命名的一致性和规范性,避免使…...
采用海豚调度器+Doris开发数仓保姆级教程(满满是踩坑干货细节,持续更新)
目录 一、采用海豚调度器+Doris开发平替CDH Hdfs + Yarn + Hive + Oozie的理由。 1. 架构复杂性 2. 数据处理性能 3. 数据同步与更新 4. 资源利用率与成本 6. 生态系统与兼容性 7. 符合信创或国产化要求 二、ODS层接入数据 接入kafka实时数据 踩坑的问题细节 三、海…...
通过将模型权重的矩阵表示为低秩矩阵,可以减少需要调整的参数数量,通俗易懂的解释,不懂你爬网线打我
通过将模型权重矩阵表示为低秩矩阵,可以减少需要调整的参数数量,原因在于低秩矩阵的结构本身就比高秩矩阵更“紧凑”,即它们需要的独立参数更少。具体来说,低秩矩阵的结构可以通过减少模型的自由度(独立参数的数量&…...
Java并发编程——线程池(基础,使用,拒绝策略,命名,提交方式,状态)
我是一个计算机专业研0的学生卡蒙Camel🐫🐫🐫(刚保研) 记录每天学习过程(主要学习Java、python、人工智能),总结知识点(内容来自:自我总结网上借鉴࿰…...
DilateFormer: Multi-Scale Dilated Transformer for Visual Recognition 中的空洞自注意力机制
空洞自注意力机制 文章目录 摘要1. 模型解释1.1. 滑动窗口扩张注意力1.2. 多尺度扩张注意力 2. 代码3. 流程图3.1. MultiDilatelocalAttention3.2. DilateAttention3.3. MLP 摘要 本文针对DilateFormer中的空洞自注意力机制原理和代码进行详细介绍,最后通过流程图梳…...
二十三种设计模式-适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将不兼容的接口转换成客户端期望的接口,从而使原本因接口不匹配而不能一起工作的类可以协同工作。以下是关于适配器模式的详细介绍: 一、定义及作用 定义&am…...
复用类(2):代理、结合使用组合和继承
1 代理 第三种关系称为代理,这是继承与组合之间的中庸之道,因为我们将一个成员对象置于所要构造的类中(就像组合),但与此同时我们在新类中暴露了该成员对象的所有方法(就像继承)。例如ÿ…...
浅谈云计算07 | 云安全机制
云计算安全机制 一、引言二、加密技术:数据的隐形护盾三、散列机制:数据完整性的忠诚卫士四、数字签名:数据来源与真伪的鉴定专家五、公钥基础设施(PKI):信任的基石六、身份与访问管理(IAM&…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
