【linux进程间通信(二)】共享内存详解以及进程互斥概念

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:Linux从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学更多操作系统知识
  🔝🔝


在这里插入图片描述

进程间通信

  • 1. 前言
  • 2. 共享内存的原理
  • 3. 实现共享内存的基本步骤
  • 4. 共享内存编码实现
  • 5. 进程互斥相关概念
  • 6. 总结

1. 前言

在学习Linux中的程序地址空间时,
善于观察的同学可能会发现在栈区
和堆区中间有一个共享区,这是用来
干啥的?今天就来揭晓一下!

本章重点:

本篇文章着重介绍进程间通信的一种
方式: 共享内存的概念,接口使用以及
它的底层原理,最后会介绍进程间互斥
的一些基本概念


2. 共享内存的原理

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据

说大白话就是: 共享内存的通信方式就是在物理内存中开辟一份空间,然后将这份空间映射到两个进程的共享区中,这两个进程可以直接在自己的地址空间中读取或写入数据,不会经过内核,效率很快!

在这里插入图片描述


3. 实现共享内存的基本步骤

使用shm系统函数来实现这一功能:

  1. 第一步: 获取key值

要通信的双方怎样保证自己看见的是和对方一样共享内存? -> 通过一个key值来保证,只要两个进程拿到同一个key值,再用这个key值去创建共享内存,那么它们看见的就是同一份共享内存!

在这里插入图片描述

使用ftok函数可以形成一个唯一的key值
函数的参数随意指定,只要保证通信双方
传入的参数一样,就能备注拿到一样的key

  1. 第二步: 创建/获取共享内存

通信双方只需要一方来创建共享内存,另外一方可以直接通过key值获取到共享内存(毕竟物理内存只需要创建一份),不管是创建还是获取共享内存使用的都是同一个函数!

在这里插入图片描述

  1. 第三步: 将共享内存映射到地址空间

当双方进程都拿到共享内存段的标识码后,此时需要将这份共享空间从物理地址映射到进程自己内部的地址空间中,方便后续使用!

在这里插入图片描述

  1. 第四步: 使用完后将共享内存与进程去关联

值得注意的是,共享内存使用完后和指针一样需要"释放",否则会导致内存泄漏问题

在这里插入图片描述

  1. 第五步: 删除共享内存

将共享内存与进程去关联后,并不代表它就被删除了,共享内存的生命周期是随内核的,而我们的云服务器是永远不会关闭的,如果不删除共享内存,将来能使用的空间会越来越少

使用ipcs -m指令查看共享内存
使用ipcrm -m shmid指令删除共享内存

函数删除共享内存的方法
在这里插入图片描述


4. 共享内存编码实现

由于双方进程编写代码有很多重复的地方
所以使用一个commom.h文件存放公共内容

commom.h文件中:

#pragma once
#include<iostream>
#include<string>
#include<unistd.h>
#include<cstdio>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<cassert>
#include<cstring>
#include<sys/stat.h>
#include<fcntl.h>
using namespace std;
#define PATHNAME "/home/kwy"  //形成key值的字符串
#define PROJ_ID 0x666  //形成key值的整数
#define SHM_SIZE 4096 //共享内存的大小最好是页(PAGE : 4096)的整数倍

client端代码:

#include"common.hpp"
int main()
{//获取keykey_t k = ftok(PATHNAME, PROJ_ID);if (k < 0){perror("ftok");exit(1);}cout<<"creat key success: "<<k<<endl;// 获取共享内存int shmid = shmget(k, SHM_SIZE, 0);if(shmid < 0){perror("shmget");exit(2);}cout<<"get shard success: "<<shmid<<endl;//挂接共享内存char *shmaddr = (char *)shmat(shmid, nullptr, 0);if(shmaddr == nullptr){perror("shmat");exit(3);}cout<<"attach success!"<<endl;//将共享内存看作数组,写入数据char ch ='a';for(;ch<='z';ch++){snprintf(shmaddr,SHM_SIZE-1,"hello server,i am other proc,mypid: %d ,inc: %c",getpid(),ch);sleep(2);}// 去关联int n = shmdt(shmaddr);assert(n != -1);cout<<"detach success!"<<endl;// client 要不要chmctl删除呢?不需要!!return 0;
}

server端代码:

#include"common.hpp"
int main()
{//创建公共的key的值key_t key = ftok(PATHNAME,PROJ_ID);cout<<"server key: "<<TransToHex(key)<<endl;assert(key!=-1);//创建共享内存(全新的共享内存)int shmid = shmget(key,SHM_SIZE,IPC_CREAT | IPC_EXCL | 0666);if(shmid==-1){perror("shmid");exit(1);}cout<<"creat shmid: "<<shmid<<endl;//将创建好的共享内容挂接到虚拟地址char* shmaddr = (char*)shmat(shmid,nullptr,0);//shmat的返回值是void*,与malloc相似要强转cout<<"attach success!"<<endl;//使用共享内存,将共享内存当作一个大字符串//使用完共享内存后,将指定的内存与进程去关联int n1 = shmdt(shmaddr);if(n1==-1)perror("shmdt");elsecout<<"detach success!"<<endl;//最后用代码删除共享内存int n2 = shmctl(shmid,IPC_RMID,nullptr);assert(n2!=-1);cout<<"delete shared memory: "<<shmid<<endl;return 0;
}

5. 进程互斥相关概念

大家在学习共享内存时有没有发现一个问题:

假如共享区有一个变量a,client进程在将a进行++操作的同时,server进程将a的值从10改为了100,这里就会出现问题,已经被改为100的a值在client进程执行完操作后,会把在CPU中计算出来的11赋值给a,那么进程server就白修改了,这里显然是有问题的

没错,在这个地方,共享内存被称为共享资源,共享资源如果被同时访问可能会出现某些预想不到的问题,所以各个进程不能在同一时间访问共享资源,这种关系叫做进程互斥

在这里插入图片描述

对于进程互斥和共享资源以及临界区的认识远远没有结束,今天我们只是窥见了冰山一角,在后续的学习中我们还会重点讲这一个概念!


6. 总结

进程间通信的方式远不止管道和共享内存这两种,还有很经典的消息队列以及信号量等方式这里并没有过多讲述,因为我们只是学习重点,并不是全部都要学会,但是学有余力的同学还是很有必要区了解一下的


🔎 下期预告:进程信号 🔍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/697053.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年2月23日 晨会汇报

Good morning, colleages! This is /ˈdɑː.tʃi/ speaking. As for my report today, I decide to wing it, so I didnt prepare a script. Now, Ill share an update about my recent work activities which encompasses two key area: a summary of my work yesterday a…

【Go channel如何控制goroutine并发执行顺序?】

多个goroutine并发执行时&#xff0c;每一个goroutine抢到处理器的时间点不一致&#xff0c;gorouine的执行本身不能保证顺序。即代码中先写的gorouine并不能保证先执行 思路&#xff1a;使用channel进行通信通知&#xff0c;用channel去传递信息&#xff0c;从而控制并发执行…

基于开源模型对文本和音频进行情感分析

应用场景 从商品详情页爬取商品评论&#xff0c;对其做舆情分析&#xff1b;电话客服&#xff0c;对音频进行分析&#xff0c;做舆情分析&#xff1b; 通过开发相应的服务接口&#xff0c;进一步工程化&#xff1b; 模型选用 文本&#xff0c;选用了通义实验室fine-tune的st…

电脑录屏软件哪个好用?实测告诉你答案(2024年最新)

在当今信息化快速发展的时代&#xff0c;无论是录制在线课程、游戏操作&#xff0c;还是制作教程、会议记录&#xff0c;一款电脑录屏软件显得尤为重要&#xff0c;可是电脑录屏软件哪个好用呢&#xff1f;本文将介绍三款主流的电脑录屏软件&#xff0c;通过分步骤详细讲述&…

使用maven集成spring在测试的时候报出了如下的异常:version 60

使用maven集成spring在测试的时候报出了如下的异常&#xff1a; Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 60 解决&#xff1a;

在word中将latex格式的公式转化为带有编号的mathtype公式

在word中将latex格式的公式转化为带有编号的mathtype公式 1.先在word里面配置好mathtype2.在word中设置mathtype的格式3.先将latex格式的公式转化为mathml格式4.读到这里&#xff0c;是不是觉得这个方法麻烦 1.先在word里面配置好mathtype 注意&#xff1a;1.word的版本应该是 …

基于springboot+vue的中小型医院网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Sovit3D数字孪生平台 助力智慧海上风电场项目加速

我们常说地球是蓝色星球&#xff0c;那是因为海洋约占地球面积的71%。如今&#xff0c;我国正在向“双碳”目标不断奋斗&#xff0c;海上风电也作为一种潜力清洁能源&#xff0c;迸发出前所未有的活力&#xff0c;海上吹来的风成为未来清洁能源新方向。 2024年海上风电项目加速…

Qt_快速安装指南

下载Qt在线安装程序&#xff08;不仔细介绍&#xff09;注册Qt账号&#xff08;不仔细介绍&#xff09;使用快速运行的命令&#xff0c;按照指定的下载地址下载 在Qt指定目录打开cmd命令窗口.\eqt-unified-windows-x86-4.0.1-1-online. exe --mirror https://mirrors.ustc.edu.…

JVM虚拟机结构

虚拟机结构图 从图中看出&#xff1a; JVM虚拟机主要有三大部分组成&#xff1a; 1. 类加载器 2. JVM运行时内存 3. 执行引擎 一、类加载器 类加载器主要用来加载字节码文件&#xff08;.class&#xff09;到内存中 二、内存结构 如图&#xff1a;可将内存分为两大部分&…

【go】IP相关工具类

文章目录 1.判断ipv4 or ipv62.计算cidr格式ip所含IP个数3.计算两个ip区间所含ip个数 1.判断ipv4 or ipv6 // return int 0:错误的ip 4:ipv4 6:ipv6 func CheckIp(ip string) int {if ip "" {return 4}out : net.ParseIP(ip)if out nil {return 0}if strings.Cont…

C1475D Cleaning the Phone 题解

文章目录 C1475D Cleaning the Phone 题解Cleaning the Phone题面翻译题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示算法&#xff1a;贪心代码&#xff1a; C1475D Cleaning the Phone 题解 link Cleaning the Phone 题面翻译 题目大意&#xff1a; 有 n …

【学习iOS高质量开发】——协议与分类

文章目录 一、通过委托与数据源协议进行对象间通信1.委托模式2.要点 二、将类的实现代码分散到便于管理的数个分类之中1.如何实现2.要点 三、总是为第三方类的分类名称加前缀1.为什么总是为第三方类的分类名称加前缀2.要点 三、勿在分类中声明属性1.勿在分类中声明属性的原因2.…

Android进阶(二十九) 走近 IntentFilter

文章目录 一、什么是IntentFilter &#xff1f;二、IntentFilter 如何过滤隐式意图&#xff1f;2.1 动作测试2.2 类别测试2.3 数据测试 一、什么是IntentFilter &#xff1f; 如果一个 Intent 请求在一片数据上执行一个动作&#xff0c; Android 如何知道哪个应用程序&#xf…

网页数据的解析提取(XPath的使用----lxml库详解)

在提取网页信息时&#xff0c;最基础的方法是使用正则表达式&#xff0c;但过程比较烦琐且容易出错。对于网页节点来说&#xff0c;可以定义id、class或其他属性&#xff0c;而且节点之间还有层次关系&#xff0c;在网页中可以通过XPath或CSS选择器来定位一个或多个节点。那么&…

Maven管理项目,本地仓库有对应的jar包,但还是报找不到

文章目录 业务场景错误提示分析过程解决办法 业务场景 settings.xml种配置了私服&#xff0c;但是有些依赖私服上没有&#xff0c;通过同事拷贝过来的。但是用maven打包时报红了。 错误提示 Idea Maven错误&#xff1a;was cached in the local repository, resolution will…

RecycleView结合ItemTouchHelper实现拖动排序

最近项目中需要实现对某一类条目进行拖动排序功能&#xff0c;实现技术方案就是利用ItemTouchHelper绑定RecyclerView、ItemTouchHelper.Callback来实现UI更新&#xff0c;并且实现动态控制是否开启拖动功能。其中&#xff0c;ItemTouchHelper是Google在androidx包中添加的&…

int128的实现(基本完成)

虽然有一个声明叫_int128但是这并不是C标准&#xff1a; long long 不够用&#xff1f;详解 __int128 - FReQuenter - 博客园 (cnblogs.com) 网络上去找int128的另类实现方法&#xff0c;发现几乎都是在介绍_int128的 然后我就自己想了个办法&#xff0c;当时还没学C&#xf…

Spring Boot中实现列表数据导出为Excel文件

点击下载《Spring Boot中实现列表数据导出为Excel文件》 1. 前言 本文将详细介绍在Spring Boot框架中如何将列表数据导出为Excel文件。我们将通过Apache POI库来实现这一功能&#xff0c;并解释其背后的原理、提供完整的流程和步骤&#xff0c;以及带有详细注释的代码示例。最…

关于设备连接有人云的使用及modbus rtu协议,服务器端TCP调试设置

有人云调试 调试过程问题1. 关于modbus rtu协议,实质上有三种modbus基本原理modbus 格式2. 关于modbus crc16通信校验3. 关于在ubuntu阿里云服务器端,监听网络数据之调试mNetAssist之前的一个项目,再拿出来回顾下。 调试过程 先 要在有人云,用手机号注册一个服务账号,官网显…