[linux]进程间通信(IPC)———共享内存(shm)(什么是共享内存,共享内存的原理图,共享内存的接口,使用演示)

一、什么是共享内存

 共享内存区是最快的(进程间通信)IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。注意:共享内存没有进行同步与互斥!共享内存不会自动销毁,要手动销毁。

二、 共享内存的原理图

三、共享内存的接口(什么用)

ftok

功能:生成一个key,key是shmget第一个参数,这个key是一个约定的数,让不同的进程通过key找到同一份资源,不用再进入内存查找。

头文件

#include <sys/types.h>
#include <sys/ipc.h>
原型
key_t ftok(const char *pathname, int proj_id);
参数

pathname:一个路径字符串,可以随便给

proj_id:一个int数据,可以随便给

返回值:返回key

shmget

功能:用来创建共享内存

头文件

#include <sys/ipc.h>
#include <sys/shm.h>
原型
int shmget(key_t key, size_t size, int shmflg);
参数
key:这个共享内存段名字,这个key是一个约定的数,让不同的进程通过key找到同一份资源
size:共享内存的大小(一般取 n * 1024)
shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的

主要用这两个:

IPC_EXCL:不存在共享内存就创建,存在就使用现有的

IPC_EXCL:不存在共享内存就创建,存在就报错,保证创建的共享内存是新的

返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1

shmat

功能:将共享内存段连接到进程地址空间

头文件

 #include <sys/types.h>
 #include <sys/shm.h>

原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数
shmid: 共享内存标识,shmget的返回值
shmaddr:指定连接的地址
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回一个指针,指向共享内存第一个节;失败返回-1

说明:
shmaddr为NULL,核心自动选择一个地址
shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表示连接操作用来只读共享内存

shmdt

功能:将共享内存段与当前进程脱离

头文件

 #include <sys/types.h>
 #include <sys/shm.h>

原型
int shmdt(const void *shmaddr);
参数
shmaddr: 由shmat所返回的指针
返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段,删除共享内存用shmctl

shmctl

功能:用于控制共享内存

头文件

 #include <sys/ipc.h>
 #include <sys/shm.h>
原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数
shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作(有三个可取值)

  1. PC STAT 把shmid ds结构中的数据设置为共享内存的当前关联值
  2. IPC SET 在进程有足够权限的前提下,把共享内存的当前关联值设置为shmid ds数据结构中给出的值
  3. IPC RMID 删除共享内存段

buf:指向一个保存着共享内存的模式状态和访问权限的数据结构,一般设为nullptr
返回值:成功返回0;失败返回-1

 四、使用演示

使用代码创建一个共享内存, 支持两个进程进行通信

 进程A 向共享内存当中写 “i am process A”

 进程B 从共享内存当中读出内容,并且打印到标准输出

 使用到的linux的一些指令

ipcs -m:查看共享内存的消息

ipcrm -m shmid:删除共享内存标识码为shmid的共享内存

监视脚本

while :; do ipcs -m; sleep 1; done
功能:每隔一秒打印一次共享内存消息

shm.hpp

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string>
#include <cstring>
#include <iostream>
#include <unistd.h>using namespace std;const string pathname = "/home/lwj/code11";
const int proj_id = 0x112233;
const int size = 4096;
key_t Getkey()
{int key = ftok(pathname.c_str(), proj_id);if(key < 0){perror("ftok");exit(-1);}return key;
}char* gethex(int x)
{char s[1024];sprintf(s, "0x%x", x);return s;}

processA.cc

#include "shm.hpp"
int main()
{key_t key = Getkey();cout << "获取key: " << gethex(key) << endl;sleep(10);//获取shmidint shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0644);cout << "创建shm, 获取shmid: " << shmid << endl; if(shmid < 0){cerr << "shmget fail" << endl;exit(-1);};sleep(10);//连接shmcout << "连接shm" << endl; char* s = (char*)shmat(shmid, nullptr, 0);sleep(10);//通信cout << "写消息" << endl;string str = "i am process A";int i = 0;for (auto e : str){s[i] = e;i++;}s[i] = '\0';//断开shmsleep(10);cout << "断开shm" << endl; shmdt(s);sleep(10);//销毁shmcout << "销毁shm" << endl; shmctl(shmid, IPC_RMID, nullptr);return 0;
}

processB.cc

#include "shm.hpp"
int main()
{key_t key = Getkey();cout << "获取key: " << gethex(key) << endl;sleep(5);// 获取shmidint shmid = shmget(key, size, IPC_CREAT);cout << "创建shm, 获取shmid: " << shmid << endl; if(shmid < 0){cerr << "shmget fail" << endl;exit(-1);}// 连接shmcout << "连接shm" << endl;char *s = (char *)shmat(shmid, nullptr, 0);sleep(5);// 通信cout << "读消息: " << s << endl;// 断开shmsleep(10);cout << "断开shm" << endl;shmdt(s);sleep(10);// 销毁shmcout << "销毁shm" << endl;shmctl(shmid, IPC_RMID, nullptr);return 0;
}

Makefile

.PHNOY:all
all:processA processBprocessA:progressA.ccg++ -o $@ $^ -std=c++11
processB:progressB.ccg++ -o $@ $^ -std=c++11.PHONY:clean
clean:rm -f processA processB

演示效果视频链接:

shm演示视频-CSDN直播

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

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

相关文章

Three.js初学(2)

Three.js初学&#xff08;2&#xff09; 三维坐标系的认识1. 辅助坐标系 光源的影响1. 光材质的影响2. 光源介绍点光源环境光平行光 3. 光源衰减/位置 相机控件1. 引入扩展库2. 使用方法 三维坐标系的认识 这一章节的主要作用是加强自我对三维坐标空间的认识。 1. 辅助坐标系…

猫头虎分享已解决Bug || TypeError: Cannot set property ‘innerHTML‘ of null

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

Kafka进阶

文章目录 概要应用场景消息队列两种模式kafka的基础架构分区常见问题小结 概要 kafka的传统定义&#xff1a;kafka是一个分布式的基于发布\订阅模式的消息队列&#xff0c;主要用于大数据实时处理领域。 kafka的最新概念&#xff1a;kafka是一个开源的分布式事件流平台&#x…

10种常见的光伏发电量计算方法

光伏发电是一种将太阳能转化为电能的清洁能源技术。随着环境保护意识的日益增强和能源结构的转型&#xff0c;光伏发电得到了广泛的应用。对于光伏系统来说&#xff0c;发电量的准确计算是评估系统性能、预测长期收益和优化系统运行的关键。以下是常见的光伏发电量计算方法&…

Python3零基础教程之Python解释器与开发环境搭建

大家好&#xff0c;我是千与编程&#xff0c;硕士毕业于北京大学&#xff0c;曾先后就职于字节跳动&#xff0c;京东等互联网大厂&#xff0c;目前在编程导航知识星球担任星球嘉宾&#xff0c;著有《AI算法毕设智囊袋》&#xff0c;《保姆级带你通关秋招教程》两大专栏。 今天开…

从it方面介绍部分好玩的电影

电影推荐 1.《黑客帝国》《The matrix》 仅推荐第一二三部2. 《代码奔腾》《code rush》3 人物传记类 《社交网络》 《硅谷传奇》 《乔布斯》4《模仿游戏》也是传记 但主演是 卷福5 《环形使者》6 《蝴蝶效应》 三部7.《隐私大盗》8.《监视资本主义&#xff1a;智能陷阱》9. 剧…

RMAN备份与恢复

文章目录 一、RMAN介绍二、全量备份三、增量备份0级备份1级增量备份累积性差量备份总结 四、压缩备份压缩备份介绍压缩备份操作压缩备份优缺点 五、异常恢复1、恢复前的准备2、恢复数据库 六、RMAN相关参数 一、RMAN介绍 RMAN&#xff08;Recovery Manager&#xff09;是Oracl…

thonny 使用命令行安装包并且替换源,安装速度嗖嗖的

thonny 使用命令行安装包并且替换源 点击 “工具”->"打开系统shell"替换源下载嘎嘎快 点击 “工具”->“打开系统shell” 替换源 pip config set global.index-url http://mirrors.aliyun.com/pypi/simple/ pip config set global.trusted-host mirrors.aliy…

快速学习安全框架 Springsecurity最新版(6.2)--用户授权模块

简介 上一节Springsecurity 用户认证 Springsecurity 拥有强大的认证和授权功能并且非常灵活&#xff0c;,一来说我们都i有以下需求 可以帮助应用程序实现以下两种常见的授权需求&#xff1a; 用户-权限-资源&#xff1a;例如张三的权限是添加用户、查看用户列表&#xff0c;李…

康威生命游戏

康威生命游戏 康威生命游戏(Conway’s Game of Life)是康威发明的细胞自动机。 生命游戏有几个简单的规则&#xff1a; 细胞有两种状态&#xff0c;存活或死亡&#xff0c;每个细胞以自身为中心与周围的八格细胞互动。 对于存活的细胞&#xff1a; 当周围的细胞过少(<2)或…

【Linux】:简易实现自动化构建代码make/Makefile

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux自动化构建代码make/makefile的使用&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&…

Leo赠书活动-18期 《高效使用Redis》

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

Ubuntu22部署MySQL5.7详细教程

Ubuntu22部署MySQL5.7详细教程 一、下载MySQL安装包二、安装MySQL三、启动MySQL检查状态登录MySQL 四、开启远程访问功能1、允许其他主机通过root访问数据库2、修改配置文件&#xff0c;允许其他IP通过自定义端口访问 五、使用Navicat连接数据库 默认情况下&#xff0c;Ubuntu2…

Android的ViewModel

前言 在Compose的学习中&#xff0c;我们在可组合函数中使用rememberSaveable​​​​​​​保存应用数据&#xff0c;但这可能意味着将逻辑保留在可组合函数中或附近。随着应用体量不断变大&#xff0c;您应将数据和逻辑从可组合函数中移出。 而在之前的应用架构学习中&…

【测试开发项目】个人博客项目测试报告

文章目录 前言 一、项目背景 二、项目功能 三、测试用例设计 3.1 个人博客项目测试用例设计 3.1.1 博客登录页测试用例设计 3.1.2 博客列表页测试用例设计 3.1.3 博客详情页测试用例设计 3.1.4 博客编辑页测试用…

从数据库中读取文件导出为Excel

使用的库&#xff08;org.apache.poi&#xff09; 在poi包中有Apache提供的各种分类文件&#xff0c;如下 结构功能HSSF读写Microsoft Excel XLS文件XSSF读写Microsoft Excel OOXML XLSX文件HWPF读写Microsoft Word DOC文件HSLF读写Microsoft PowerPoint文件 下面以XSSF为例&…

【STM32学习】——续上:软件SPI读写W25Q64SPI通信外设硬件SPI读写W25Q64

四、软件SPI读写W25Q64 工程思路与I2C类似&#xff0c;MySPI.c是通信底层&#xff0c;主要包括通信引脚封装、初始化、SPI通信的三个拼图&#xff08;起始、终止和交换一个字节&#xff09;&#xff1b;基于此文件建立W25Q64.c&#xff0c;调用MySPI三个拼图&#xff0c;拼接成…

Flutter插件开发指南01: 通道Channel的编写与实现

Flutter插件开发指南01: 通道Channel的编写与实现 视频 https://www.bilibili.com/video/BV1ih4y1E7E3/ 前言 本文将会通过一个加法计算&#xff0c;来实现 Channel 的双向通讯&#xff0c;让大家有个一个体会。 Flutter插件 Flutter插件是Flutter应用程序与原生平台之间的桥…

ES6内置对象 - Set

Set&#xff08;es6提供的一种数据结构&#xff0c;类似数组&#xff0c;是一个集合&#xff0c;可以存储任何类型的元素且唯一、不重复&#xff0c;so,多用于元素去重&#xff09; 如上图&#xff0c;Set数据结构自带一些方法 1.Set对象创建 let a new Set([1,2,3,3,1,2,4,…

linux 系统的目录结构

为什么某些执行程序位于/bin、/sbin、/usr/bin或/usr/sbin目录下&#xff1f;例如&#xff0c;less命令位于/usr/bin目录下。为什么不是/bin、/sbin或/usr/sbin&#xff1f;这些目录之间有什么区别呢&#xff1f; 在这篇文章中&#xff0c;让我们主要讲述一下Linux文件系统结构…