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

linux多线(进)程编程——(6)共享内存

前言

话说进程君的儿子经过父亲点播后就开始闭关,它想要开发出一种全新的传音神通。他想,如果两个人的大脑生长到了一起,那不是就可以直接知道对方在想什么了吗,这样不是可以避免通过语言传递照成的浪费吗?
下面就是它的设计思路。

共享内存

进程间的通信手段分别有:管道,共享内存,消息队列,信号,信号量,套接字。今天我们将学习第二种方式,共享内存(Shared Memory)。这也是进程间通信最为高效的方式。
共享内存的原理其实很简单,进程间由于操作系统的内存映射,实现了物理内存的隔离。如果有一种方法可以让两个进程的内存同时映射到一块物理内存上,那么这块内存内的数据就对两个进程全部可见了。我们也可以直接通过指针访问对应的内存空间实现进程间数据的高效传输。
共享内存的原理示意图

共享内存的使用

linux系统为共享内存提供了以下几个函数接口,它们以shm开头,表示Shared Memory
(1)向系统申请获取共享

int shmget(ket_t __key, size_t __size, int __shmflg);

这个函数用于向系统申请一块共享内存。
__key:共享内存的键值,这个键值用于在不同进程间标识为一的共享功能区
__size:共享内存的大小(单位:字节),对于相同键值,大小要保持一致
__shmflg:共享内存申请方式
return val:返回共享内存的ID号

(2)挂载共享内存

void* shmat(int __shmid, const void *shmaddr, int __shmflg);

这个函数用于将共享内存挂载到进程内部的虚拟地址上,使用这个函数后就可以直接使用指针操作共享内存
__shmid:共享内存ID
__shmaddr:希望挂载到地址,为NULL由系统自行分配
__shmflg:一般值为0即可
return val:返回共享内存在进程中的虚拟地址的值

(3)分离共享内存

int shmdt(const void *__shmaddr);

这个函数用于将共享内存与进程的虚拟内存分离。
__shmaddr:指向共享内存的虚拟地址

(4)控制共享内存

int shmctl(int __shmid, int __command, struct shmid_ds *__buf);

用来对共享内存执行一些操作,用来告诉系统释放共享内存
__shmid:共享内存ID
__command:要执行的指令,为IPC_RMID时用来告诉系统释放共享内存
__buf:为NULL即可(高级用法一般用不到)

代码案例

运行两个程序,申请共享内存后一个写入hello world,另一个程序读取。
pro1.c:写入数据

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include <string.h>#define SHMSIZE 20		// 共享内存大小,与pro2.c保持一致,否则一定报错int main() {int ID = shmget((key_t)1, SHMSIZE, 0666|IPC_CREAT);		// 申请共享内存,键值为1,与pro2.c保持一致char* shm_addr = shmat(ID, NULL, 0);	// 挂载到进程的虚拟内存地址上char str[SHMSIZE] = "hello, world!";	memcpy(shm_addr, str, sizeof(str));		// 使用指针 shm_addr 操作共享内存shmdt(shm_addr);						// 分离共享内存return 0;
}

pro2.c读取数据

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>#define SHMSIZE 20 		// 共享内存大小,与pro1.c保持一致,否则一定报错int main() {int ID = shmget((key_t)1, SHMSIZE, 0666|IPC_CREAT);		// 申请共享内存,键值为1,与pro2.c保持一致char* shm_addr = shmat(ID, NULL, 0);printf("%s\n", shm_addr); 		// 打印数据shmdt(shm_addr);shmctl(ID, IPC_RMID, NULL);		// 释放共享内存,不然即使关闭程序也会内存泄露,共享内存不会回收return 0;
}

运行结果

lol@hyl:~/work/linux_study/Shared_memory/shm_fun$ gcc -o p1 pro1.c
lol@hyl:~/work/linux_study/Shared_memory/shm_fun$ gcc -o p2 pro2.c
lol@hyl:~/work/linux_study/Shared_memory/shm_fun$ ./p1
lol@hyl:~/work/linux_study/Shared_memory/shm_fun$ ./p2
hello, world!

进程2顺利输出hello, world!

注意事项

(1)共享内存操作不规范导致冲突

当共享内存使用不规范,例如发生(1)大小不匹配、(2)未调用shmctl(ID, IPC_RMID, NULL)释放内存等情况时,系统会出现内存报错。 此时程序无法再次运行!即使关闭编译器后再次打开,仍然无法运行,因此共享内存仍然在系统内。
应对这种情况,需要在命令行输入

ipcs -m

之后终端会显示:


------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000001 6          hyl        666        20         0    

在这里我们可以看到我们申请的键值为1的ID号为6的共享内存,大小为20个字节,正是它的存在让我们无法再次以键值1申请共享内存,我们需要手动释放这块内存。

在命令行输入

ipcrm -m 6

最后的数字是共享内存的ID,删除后我们就可以再次运行程序了,要记得操作规范,及时在程序中释放哦!

共享内存的进程间安全问题

申请共享内存后,当两个进程想要同时向内存中写入数据会发生什么?
这个问题是一个很复杂的问题,涉及到进程间的安全性问题,学名叫进程间竞态竞争。我们将在信号量的学习中解决它,这里不过多赘述。
(我们展示的程序逻辑很简单,而且有先后运行顺序,不需要担心出现进程间冲突的问题)

小结

这节课我们学习了进程间通信的最高效手段——共享内存。
主要知识点:
(1)共享内存的四个接口函数:shmget、shmat,shmdt、shmctl
(2)共享内存的操作注意事项:大小一致,即使回收
(3)命令行中查看共享内存的指令(ipcs -m)与命令行中删除共享内存的指令(ipcrm -m shmid)

下一节我们将学习:消息队列

结束语

进程君的儿子在领悟到共享内存后,在修真界名声大振,隐隐有赶超其父亲的趋势。被人尊称为:进程公。(青出于蓝胜于蓝)

番外:什么!共享内存的另一种申请方式?

相关文章:

linux多线(进)程编程——(6)共享内存

前言 话说进程君的儿子经过父亲点播后就开始闭关&#xff0c;它想要开发出一种全新的传音神通。他想&#xff0c;如果两个人的大脑生长到了一起&#xff0c;那不是就可以直接知道对方在想什么了吗&#xff0c;这样不是可以避免通过语言传递照成的浪费吗&#xff1f; 下面就是它…...

【愚公系列】《Python网络爬虫从入门到精通》050-搭建 Scrapy 爬虫框架

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…...

信息安全管理与评估2021年国赛正式卷答案截图以及十套国赛卷

2021年全国职业院校技能大赛高职组 “信息安全管理与评估”赛项 任务书1 赛项时间 共计X小时。 赛项信息 赛项内容 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 平台搭建与安全设备配置防护 任务1 网络平台搭建 任务2 网络安全设备配置与防护 第二…...

讲解贪心算法

贪心算法是一种常用的算法思想&#xff0c;其在解决问题时每一步都做出在当前状态下看起来最优的选择&#xff0c;从而希望最终能够获得全局最优解。C作为一种流行的编程语言&#xff0c;可以很好地应用于贪心算法的实现。下面我们来讲一篇关于C贪心算法的文章。 目录 贪心算法…...

高并发秒杀系统设计:关键技术解析与典型陷阱规避

电商、在线票务等众多互联网业务场景中&#xff0c;高并发秒杀活动屡见不鲜。这类活动往往在短时间内会涌入海量的用户请求&#xff0c;对系统架构的性能、稳定性和可用性提出了极高的挑战。曾经&#xff0c;高并发秒杀架构设计让许多开发者望而生畏&#xff0c;然而&#xff0…...

微信小程序实战案例 - 餐馆点餐系统 阶段 2 – 购物车

阶段 2 – 购物车&#xff08;超详细版&#xff09; 目标 把“加入购物车”做成 全局状态&#xff0c;任何页面都能读写在本地 持久化&#xff08;关闭小程序后购物车仍在&#xff09;新建 购物车页&#xff1a;数量增减、总价实时计算、去结算入口打 Git Tag v2.0‑cart 1. …...

Qt 元对象系统探秘:从 Q_OBJECT 到反射编程的魔法之旅

背景说明&#xff1a;Qt 背后的「魔法引擎」 如果你曾用 Qt 写过信号槽&#xff0c;或是在设计器里拖过控件改属性&#xff0c;一定对这个框架的“动态性”印象深刻&#xff1a; 无需手动调用&#xff0c;信号能自动连接到槽函数&#xff1b;无需编译重启&#xff0c;界面上修…...

sql 向Java的映射

优化建议&#xff0c;可以在SQL中控制它的类型 在 MyBatis 中&#xff0c;如果返回值类型设置为 java.util.Map&#xff0c;默认情况下可以返回 多行多列的数据...

Visual Studio未能加载相应的Package包弹窗报错

环境介绍&#xff1a; visulal studio 2019 问题描述&#xff1a; 起因&#xff1a;安装vs扩展插件后&#xff0c;重新打开Visual Studio&#xff0c;报了一些列如下的弹窗错误&#xff0c;即使选择不继续显示该错误&#xff0c;再次打开后任然报错&#xff1b; 解决思路&am…...

【HD-RK3576-PI】Docker搭建与使用

硬件&#xff1a;HD-RK3576-PI 软件&#xff1a;Linux6.1Ubuntu22.04 1.Docker 简介 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言开发&#xff0c;遵循 Apache 2.0 协议。它可以让开发者将应用程序及其依赖项打包到一个轻量级、可移植的容器中&#xff0c;并在任…...

C语言实现用户管理系统

以下是一个简单的C语言用户管理系统示例&#xff0c;它实现了用户信息的添加、删除、修改和查询功能。代码中包含了详细的注释和解释&#xff0c;帮助你理解每个部分的作用。 #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAX_USERS…...

【websocket】使用案例( ​JSR 356 标准)

目录 一、JSR 356方式&#xff1a;简单示例 1、引入依赖 2、注册端点扫描器 3、编写通过注解处理生命周期和消息 4、细节解读 5、总结 二、聊天室案例 方案流程 1、引入依赖 2、注册端点扫描器 3、编写一个配置类&#xff0c;读取httpsession 4、编写通过注解处理生…...

tcpdump`是一个非常强大的命令行工具,用于在网络上捕获并分析数据包

通过 tcpdump&#xff0c;你可以抓取网络流量&#xff0c;诊断网络问题&#xff0c;或分析通信协议的细节。下面是如何在 Linux 上使用 tcpdump 进行抓包的详细步骤。 1. 安装 tcpdump 在大多数 Linux 发行版中&#xff0c;tcpdump 是默认安装的。如果没有安装&#xff0c;可…...

IS-IS中特殊字段——OL过载

文章目录 OL 过载位 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Datacom专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年04月13日20点12分 OL 过载位 路由过载 使用 IS-IS 的过载标记来标识过载状态 对设备设置过载标记后&#xff…...

【时频谱分析】快速谱峭度

算法配置页面&#xff0c;也可以一键导出结果数据 报表自定义绘制 获取和下载【PHM学习软件PHM源码】的方式 获取方式&#xff1a;Docshttps://jcn362s9p4t8.feishu.cn/wiki/A0NXwPxY3ie1cGkOy08cru6vnvc...

Spring Boot 支持的内嵌服务器(Tomcat、Jetty、Undertow、Netty(用于 WebFlux 响应式应用))详解

Spring Boot 支持的内嵌服务器详解 1. 支持的内嵌服务器 Spring Boot 默认支持以下内嵌服务器&#xff1a; Tomcat&#xff08;默认&#xff09;JettyUndertowNetty&#xff08;用于 WebFlux 响应式应用&#xff09; 2. 各服务器使用示例 (1) Tomcat&#xff08;默认&#xf…...

微软Exchange管理中心全球范围宕机

微软已确认Exchange管理中心&#xff08;Exchange Admin Center&#xff0c;EAC&#xff09;发生全球性服务中断&#xff0c;导致管理员无法访问关键管理工具。该故障被标记为关键服务事件&#xff08;编号EX1051697&#xff09;&#xff0c;对依赖Exchange Online的企业造成广…...

基于AI的Web应用防火墙(AppWall)实战:漏洞拦截与威胁情报集成

摘要&#xff1a;针对Web应用面临的OWASP、CVE等漏洞攻击&#xff0c;本文结合群联AI云防护系统的AppWall模块&#xff0c;详解AI规则双引擎的防御原理&#xff0c;并提供漏洞拦截配置与威胁情报集成代码示例。 一、Web应用安全挑战与AppWall优势 传统WAF依赖规则库更新滞后&a…...

基于Qt的串口通信工具

程序介绍 该程序是一个基于Qt的串口通信工具&#xff0c;专用于ESP8266 WiFi模块的AT指令配置与调试。主要功能包括&#xff1a; 1. 核心功能 串口通信&#xff1a;支持串口开关、参数配置&#xff08;波特率、数据位、停止位、校验位&#xff09;及数据收发。 AT指令操作&a…...

CSS 字体学习笔记

在网页设计中&#xff0c;字体的使用对于提升用户体验和页面美观性至关重要。CSS 提供了一系列字体属性&#xff0c;用于控制文本的显示效果。以下是对 CSS 字体属性的详细学习笔记。 一、字体系列&#xff08;font-family&#xff09; 1. 字体系列的分类 在 CSS 中&#xf…...

《MySQL是怎样运行的》总结笔记

内容太多&#xff0c;主要总结一些自己认为重要的&#xff0c;另外太基础常见可能不会总结上。 字符集和比较规则 MySQL会通过把字符串编码后再进行比较大小并排序&#xff0c;有一些很早的字符集可能会不支持中文&#xff0c;比如ASCII、ISO 8859-1&#xff0c;现在最常用的…...

力扣每日打卡 1922. 统计好数字的数目 (中等)

力扣 1922. 统计好数字的数目 中等 前言一、题目内容二、解题方法1. 暴力解法&#xff08;会超时&#xff0c;此法不通&#xff09;2. 快速幂运算3. 组合计数的思维逻辑分析组合计数的推导例子分析思维小结论 4.官方题解4.1 方法一&#xff1a;快速幂 三、快速幂运算快速幂运算…...

上层 Makefile 控制下层 Makefile 的方法

在复杂的项目中&#xff0c;通常会将项目划分为多个模块或子项目&#xff0c;每个模块都有自己的 Makefile。上层 Makefile 的作用是协调和控制这些下层 Makefile 的构建过程。下面是几种常见的示例&#xff0c;实现上层 Makefile 对下层 Makefile 的控制。 直接调用&#xff1…...

html简易实现推箱子小游戏原理(易上手)

实现效果 使用方向键移动&#xff0c;将橙色箱子推到绿色目标区域&#xff08;黑色块为墙&#xff0c;白色块为可通过区域&#xff0c;蓝球为小人&#xff09; 实现过程 <!DOCTYPE html> <html> <head><title>推箱子小游戏</title><style&g…...

搭建一个Spring Boot聚合项目

1. 创建父项目 打开IntelliJ IDEA&#xff0c;选择 New Project。 在创建向导中选择 Maven&#xff0c;确保选中 Create from archetype&#xff0c;选择 org.apache.maven.archetypes:maven-archetype-quickstart。 填写项目信息&#xff1a; GroupId&#xff1a;com.exampl…...

字符串与栈和队列-算法小结

字符串 双指针 反转字符串(双指针) 力扣题目链接 void reverseString(vector<char>& s) {for (int i 0, j s.size() - 1; i < s.size()/2; i, j--) {swap(s[i],s[j]);} }反转字符串II 力扣题目链接 遍历字符串的过程中&#xff0c;只要让 i (2 * k)&#…...

类似东郊到家的上门按摩预约服务系统小程序APP源码全开源

&#x1f525; 为什么上门按摩正在席卷全国&#xff1f; 万亿蓝海市场爆发 2024年中国按摩市场规模突破8000亿&#xff0c;上门服务增速达65% 90后成消费主力&#xff0c;**72%**白领每月至少使用1次上门按摩&#xff08;数据来源&#xff1a;艾媒咨询&#xff09; 传统痛点…...

Python | 在Pandas中按照中值对箱形图排序

箱形图是可视化数据分布的强大工具&#xff0c;因为它们提供了对数据集内的散布、四分位数和离群值的洞察。然而&#xff0c;当处理多个组或类别时&#xff0c;通过特定的测量&#xff08;如中位数&#xff09;对箱形图进行排序可以提高清晰度并有助于揭示模式。在本文中&#…...

[实战] 二分查找与哈希表查找:原理、对比与C语言实现(附完整C代码)

二分查找与哈希表查找&#xff1a;原理、对比与C语言实现 一、引言 在计算机科学中&#xff0c;高效的数据查找是核心问题之一。本文深入解析两种经典查找算法&#xff1a;二分查找与哈希表查找&#xff0c;从算法原理、时间复杂度、适用场景到完整C语言实现&#xff0c;提供…...

游戏引擎学习第215天

总结并为今天做铺垫 今天的工作内容是解决调试系统中的一个小问题。昨天我们已经完成了大部分的调试系统工作&#xff0c;但还有一个小部分没有完全处理&#xff0c;那就是关于如何层次化组织数据的问题。我们遇到的一个问题是&#xff0c;演示代码中仍有一个尚未解决的部分&a…...