Linux下进程间的通信--共享内存
共享内存概述:
共享内存是进程间通信的一种方式,它允许两个或多个进程共享一个给定的存储区。共享内存是最快的一种IPC形式,因为它允许进程直接对内存进行读写操作,而不需要数据在进程之间复制。
共享内存是进程间通信(IPC)中效率非常高的一种方式,因为它允许多个进程直接访问同一块内存区域,从而避免了数据在进程间复制的开销。这种直接访问内存的方式减少了数据传输的时间,提高了通信效率。
在 Linux 系统中通过 ipcs -m 查看所有的共享内存
1.创建共享内存:
shmget()
是一个在 Linux 系统上用于创建或获取共享内存段的系统调用
shmget()函数描述:
函数头文件:
#include <sys/ipc.h>
#include <sys/shm.h>函数原型:
int shmget(key_t key, size_t size, int shmflg);函数参数:
key_t key: 这是一个键值,用于标识共享内存段。如果key是IPC_PRIVATE,则创建一个新的共享内存段,并且不与其他任何共享内存段关联。
size_t size: 这是共享内存段的大小,以字节为单位。这个大小必须是一个系统页的整数倍。
int shmflg: 这是一组标志位,用于控制共享内存段的权限和控制选项。
常见的标志位包括:
IPC_CREAT: 如果指定了这个标志,并且key指定的共享内存段不存在,则创建一个新的共享内存段。
IPC_EXCL: 与IPC_CREAT一起使用,如果共享内存段已经存在,则shmget()调用失败。
0666 (八进制): 这是权限掩码,用于设置共享内存段的权限。默认情况下,所有用户都可以读写共享内存段。函数返回值:
成功:返回一个有效的共享内存标识符
失败:返回-1,并设置errno来指示错误
错误原因:
EACCES: 没有权限访问共享内存段。
EEXIST: IPC_CREAT | IPC_EXCL 被设置,但共享内存段已经存在。
EINVAL: size不是系统页大小的整数倍,或者key是无效的。
ENOMEM: 系统内存不足,无法创建新的共享内存段
扩充知识--系统页大小:
在Linux系统中,"系统页面大小"(也称为"页大小"或"分页大小")是指操作系统用于管理内存的分配单元的大小。这个大小是虚拟内存系统中页表条目的大小,也是内存管理单元(MMU)分页机制的基础。
系统页面大小通常是4KB(即4096字节),但这个值可能会根据不同的体系结构和操作系统的实现而有所不同。例如,在某些64位体系结构上,页面大小可能是8KB或更大。这个大小对于性能优化很重要,因为它决定了内存映射和页表条目的效率。
示例代码:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <string.h>int main() {size_t size = 1024; // 分配1024字节int shmflg = 0666 | IPC_CREAT; // 设置权限并创建共享内存int shmid = shmget(IPC_PRIVATE, size, shmflg);if (shmid == -1) {fprintf(stderr, "shmget failed: %s\n", strerror(errno));return 1;}printf("Shared memory ID: %d\n", shmid);return 0;
}
2.附加共享内存:
shmat()
是一个在 Linux 系统中用于将共享内存段附加到调用进程的地址空间的系统调用。这个函数是共享内存 IPC 机制的一部分,它允许进程访问由 shmget()
创建的共享内存段
shmat()函数描述:
函数头文件:
#include <sys/types.h>
#include <sys/shm.h>函数原型:
void *shmat(int shmid, const void *shmaddr, int shmflg);函数参数:
int shmid: 这是由shmget()函数返回的共享内存段的标识符。
const void *shmaddr: 这是一个可选的指针,指定共享内存段应该被附加到进程地址空间的哪个位置。
如果设置为NULL,系统会自动选择一个合适的地址。int shmflg: 这是一个标志位,用于控制共享内存的附加行为。
可能的标志包括:
SHM_RDONLY: 将共享内存附加为只读。
SHM_RND: 将共享内存附加到一个页面边界地址,这可以提高内存访问的效率。函数返回值:
成功:返回附加的共享内存段的地址
失败:返回(void *) -1,并设置errno以指示错误的原因。
错误原因
EACCES 调用进程没有请求的附加类型所需的权限,
并且在管理IPC命名空间的用户命名空间中没有CAP_IPC_OWNER功能。EIDRM shmid指向一个已删除的标识符。EINVAL 无效的shmid值,未对齐(即未对齐页面且未指定SHM_RND)或无效的shmaddr值,
或者不能在shmaddr上附加段,或者指定了SHM_REMAP而shmaddr被指定NULL。ENOMEM 无法为描述符或页表分配内存。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <string.h>int main() {int shmid; // 共享内存标识符char *shared_memory; // 共享内存的指针// 创建一个共享内存段shmid = shmget(IPC_PRIVATE, 1024, 0666 | IPC_CREAT);if (shmid == -1) {perror("shmget");exit(1);}将共享内存附加到其地址空间shared_memory = (char *)shmat(shmid, NULL, 0);if (shared_memory == (char *)(-1)) {perror("shmat");exit(1);}// 写入一些数据到共享内存strcpy(shared_memory, "Hello, World!");return 0;
}
3.分离共享内存:
当进程不再需要访问共享内存时,可以使用 shmdt
系统调用将其从进程的地址空间中分离。
shmdt()函数描述: 
函数头文件:
#include <sys/types.h>
#include <sys/shm.h>函数原型:
int shmdt(const void *shmaddr);函数参数:
shmaddr: 这是之前通过shmat()函数附加的共享内存段的地址。函数返回值
成功:返回0。
失败:返回-1,并设置errno以指示错误。
错误原因:
EINVAL: 在shmaddr上没有附加共享内存段;或者shmaddr没有在页边界上对齐
4.读写共享内存:
一旦共享内存段被附加到进程的地址空间,进程就可以通过指针直接访问和操作共享内存中的数据。这使得共享内存成为进程间通信(IPC)中非常快速和高效的一种方式。
一旦共享内存段被附加,进程就可以通过指针 shmaddr
读写共享内存。这部分内存就像普通的内存一样使用
示例代码:
void* addr = shmat(shmid,NULL,0);
if(addr == (void*)-1)
{perror("shmat");exit(EXIT_FAILURE);
}
char buf[1024]={0};
memcpy(buf,addr,10);
printf("share memory content:%s\n",buf);
shmdt(addr); //分离共享内存
5.控制共享内存:
在Linux中,共享内存的控制通常通过 shmctl
系统调用来实现。shmctl
函数可以对共享内存段进行多种操作,包括获取共享内存的状态、设置共享内存的状态以及删除共享内存段。
shmctl()函数描述:
函数头文件:
#include <sys/ipc.h>
#include <sys/shm.h>函数原型:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);:函数参数:
shmid:共享内存段的标识符,这个标识符是通过shmget()函数创建共享内存段时返回的。
cmd:指定要执行的控制操作。
它可以是以下命令之一:
IPC_STAT:获取共享内存段的状态信息,buf指向的结构会被填充。
IPC_SET:设置共享内存段的属性,buf指向的结构包含了要设置的值。
IPC_RMID:删除共享内存段,只有拥有适当权限的用户(通常是创建者或超级用户)可以执行此操作。
SHM_LOCK:锁定共享内存段,防止其被交换出物理内存。
SHM_UNLOCK:解锁共享内存段,允许其被交换。
IPC_INFO:获取系统范围内共享内存的信息(Linux 特定)。
SHM_INFO:获取系统范围内共享内存的详细信息(Linux 特定)。
SHM_STAT_ANY:获取任何用户的共享内存段的状态信息(Linux 特定,自 Linux 4.17 起支持)。buf:指向shmid_ds结构的指针,该结构用于存储共享内存段的信息或新属性
函数返回值:
成功:0
失败:-1,并设置errno以指示错误原因
shmid_ds结构体:
示例代码:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main() {int shmid;struct shmid_ds shminfo;shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666);// 获取共享内存段的信息if (shmctl(shmid, IPC_STAT, &shminfo) == -1) {perror("shmctl IPC_STAT");return 1;}printf("Size: %ld\n", (long)shminfo.shm_segsz);printf("Last attached: %ld\n", (long)shminfo.shm_nattch);// 删除共享内存段if (shmctl(shmid, IPC_RMID, &shminfo) == -1) {perror("shmctl IPC_RMID");exit(EXIT_FAILURE);}return 0;
}
结语:
无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力
相关文章:

Linux下进程间的通信--共享内存
共享内存概述: 共享内存是进程间通信的一种方式,它允许两个或多个进程共享一个给定的存储区。共享内存是最快的一种IPC形式,因为它允许进程直接对内存进行读写操作,而不需要数据在进程之间复制。 共享内存是进程间通信ÿ…...
Big Data 流处理框架 Flink
Big Data 流处理框架 Flink 什么是 FlinkFlink 的主要特性典型应用场景 Amazon Elastic MapReduce (EMR) VS Flink架构和运行时环境实时处理能力开发和编程模型操作和管理应用场景总结 Flink 支持的数据源Flink 如何消费 AWS SQS 数据源自定义 Source FunctionFlink Connector …...

校园水电费管理微信小程序的设计与实现+ssm(lw+演示+源码+运行)
校园水电费管理小程序 摘 要 随着社会的发展,社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景,运用软件工程原理和开发方法,它主要是采用java语言技术和mysql数据库来…...

HashMap线程不安全|Hashtable|ConcurrentHashMap
文章目录 常见集合线程安全性HashMap为什么线程不安全?怎么保证HashMap线程安全 HashtableConcurrentHashMap 引入细粒度锁代码中分析总结 小结 常见集合线程安全性 ArrayList、LinkedList、TreeSet、HashSet、HashMap、TreeMap等都是线程不安全的。 HashTable是线…...
01 会计概述
会计的定义:会计是以货币为计量单位,反映和监督一个单位经济活动的一种经济管理活动。会计的作用:就是提供决策信息、促使企业加强经营管理、考核管理层经济责任履行情况。会计人员职业道德:坚持诚信,守法奉公…...

开放式激光振镜运动控制器在Ubuntu+Qt下的文本标刻
开放式激光振镜运动控制器在UbuntuQt下的文本标刻 上节课程我们讲述了如何通过UbuntuQt进行振镜校正(详情点击→开放式激光振镜运动控制器在UbuntuQt下的激光振镜校正),本节文本标刻是在振镜校正的前提下实现的。 在正式学习之前࿰…...

推荐3款AIai论文大纲一键生成文献,精选整理!
在当前的学术写作环境中,AI论文大纲生成工具已经成为许多学者和学生的重要助手。这些工具不仅能够快速生成高质量的论文大纲,还能提供内容填充、文献引用和查重修改等全方位的服务。以下是三款值得推荐的AI论文大纲一键生成文献工具:千笔-AIP…...

数据库之索引<保姆级文章>
目录: 一. 什么是索引 二. 索引应该选择哪种数据结构 三. MySQL中的页 四. 索引分类及使用 一. 什么是索引: 1. MySQL的索引是⼀种数据结构,它可以帮助数据库高效地查询、更新数据表中的数据。 索引通过 ⼀定的规则排列数据表中的记录&#x…...

多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测
多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测 目录 多维时序 | Matlab基于BO-LSSVM贝叶斯优化最小二乘支持向量机数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于BO-LSSVM贝叶斯优化最小二乘支…...

Netty笔记03-组件Channel
文章目录 Channel概述Channel 的概念Channel 的主要功能Channel 的生命周期Channel 的状态Channel 的类型channel 的主要方法 ChannelFutureCloseFuture💡 netty异步提升的是什么要点总结 Channel概述 Channel 的概念 在 Netty 中,Channel 是一个非常重…...

1----安卓机型修复串码 开启端口 檫除基带 支持高通与MTK机型工具预览与操作解析
在玩机过程中。很多玩家会碰到各种各样的故障 。其中最多的就在于基带 串码类。由于目前的安卓机型必须修改或者写入串码等参数必须开启端口。而一些初级玩友不太了解开启参数端口的步骤。这个工具很简单的为安卓机型开启端口。并且操作相对简单。 此工具基本功能 1-----可以…...

Docker容器技术1——docker基本操作
Docker容器技术 随着云计算和微服务架构的普及,容器技术成为了软件开发、测试和部署过程中的重要组成部分。其中,Docker作为容器技术的代表之一,以其简便易用的特点赢得了广大开发者的青睐。 Docker允许开发者在轻量级、可移植的容器中打包和…...
ElasticSearch介绍+使用
ElasticSearch 1.背景 ElasticSearch的最明显的优势在于其分布式特性,能够扩展到上百台服务器,极大地提高了服务器的容错率。在大数据时代背景下,ElasticSearch与传统的数据库相比较,能够应对大规模的并发搜索请求,同…...

Redis——常用数据类型List
目录 List列表常用命令lpushlpushxrpushrpushlrangelpoprpoplindexlinsertllenlremltrim key start stoplset 阻塞版本命令blpopbrpop list的编码方式list的应用 List列表 Redis中的list相当于数组,或者 顺序表,一些常用的操作可以通过下面这张图来理解…...

前端基础知识+算法(一)
文章目录 算法二分查找条件注意方式基本原理左闭右闭正向写法 左闭右开正向写法 前端基础知识定时器及清除盒子垂直水平居中的方式垂直水平1.flex布局2.grid布局3.定位对于块级元素 解决高度塌陷的方式1.给父元素一个固定的高度2.给父元素添加属性 overflow: hidden;3.在子元素…...

photozoom classic 9解锁码2024年最新25位解锁码
photozoom classic 9 破解版顾及比恐龙还要稀有,我曾经和你一样一直再找,找了好几个月,也没有找到真的破解版,下载很多次, 都是病毒插件之类的 我昨天下了几次,没有一个不附带插件病毒木马的.......&#x…...

Oracle发邮件功能:设置的步骤与注意事项?
Oracle发邮件配置教程?如何实现Oracle发邮件功能? Oracle数据库作为企业级应用的核心,提供了内置的发邮件功能,使得数据库管理员和开发人员能够通过数据库直接发送邮件。AokSend将详细介绍如何设置Oracle发邮件功能。 Oracle发邮…...
优化理论及应用精解【9】
文章目录 二次型函数二次型函数详细解释一、定义二、性质三、应用四、示例五、图表辅助说明(由于文本限制,无法直接提供图表) “西尔维斯特准则”一、定义二、来源三、应用场景 参考文献 二次型函数 二次型函数详细解释 一、定义 二次型函…...

nginx实现https安全访问的详细配置过程
文章目录 前言什么是 HTTP?什么是 HTTPS?HTTP 和 HTTPS 的区别为什么 HTTPS 被称为安全的?配置过程配置自签名证书 前言 首先我们来简单了解一下什么是http和https以及他们的区别所在. 什么是 HTTP? HTTP,全称为“超…...
1. TypeScript基本语法
TypeScript 学习总结 TypeScript 是一种 JavaScript 的超集,增加了静态类型检查和编译时错误检测,从而提高了代码的可维护性和可靠性。以下是 TypeScript 的基础知识总结,包括语法、运算符、数据类型、变量声明和作用域。 ## 基本语法TypeS…...
React从基础入门到高级实战:React 核心技术 - 错误处理与错误边界:构建稳定的应用
React 错误处理与错误边界:构建稳定的应用 在开发 React 应用时,错误处理是确保应用稳定性和用户体验的重要环节。无论是运行时错误、API 请求失败还是用户操作失误,合理的错误处理机制都能防止应用崩溃,并为用户提供清晰友好的反…...
【25.06】FISCOBCOS使用caliper自定义测试 通过webase 单机四节点 helloworld等进行测试
前置条件 安装一个Ubuntu20+的镜像 基础环境安装 Git cURL vim jq sudo apt install -y git curl vim jq Docker和Docker-compose 这个命令会自动安装docker sudo apt install docker-compose sudo chmod +x /usr/bin/docker-compose docker versiondocker-compose vers…...

机器学习——SVM
1.什么是SVM 支持向量机(support vector machines,SVM)是一种二分类模型,它将实例的特征向量映射为空间中的一些点,SVM 的目的就是想要画出一条线,以 “最好地” 区分这两类点,以至如果以后有了…...
嵌入式Linux系统中的启动分区架构
在嵌入式Linux系统架构中,Linux内核、设备树(Device Tree)与引导配置文件构成了系统启动的基础核心。如何安全、高效地管理这些关键文件,直接影响到系统的稳定性与可维护性。近年来,越来越多的嵌入式Linux开发者选择将启动相关文件从传统的“混合存放”方式,转向采用独立…...
MyBatis分页插件(以PageHelper为例)与MySQL分页语法的关系
MyBatis分页插件(以PageHelper为例)与MySQL分页语法关系总结 MyBatis的分页插件(如PageHelper)底层实现依赖于数据库的分页语法。对于MySQL数据库来说,其分页逻辑最终会转化为LIMIT语句,下面展开详细说明&…...
[内核开发手册] ARM汇编指令速查表
ARM汇编指令速查表 指令描述语法示例push将一个或多个寄存器的值压入栈中,更新栈指针寄存器。push {r1, r2, r3}add执行加法并将结果存储到目标操作数中。add r1, r2, #5push.w将指定的寄存器的值压入栈中,并将栈指针向下调整4个字节。push.w {r4, r5, …...
【算法训练营Day04】链表part2
文章目录 两两交换链表中的节点删除链表的倒数第 N 个结点链表相交环形链表 II链表总结 两两交换链表中的节点 题目链接:24. 两两交换链表中的节点 算法逻辑: 添加一个虚拟头节点初始化一个交换指针,代表每次交换指针的后两个节点࿰…...

【CF】Day69——⭐Codeforces Round 897 (Div. 2) D (图论 | 思维 | DFS | 环)
D. Cyclic Operations 题目: 思路: 非常好的一题 对于这题我们要学会转换和提取条件,从特殊到一般 我们可以考虑特殊情况先,即 k n 和 k 1时,对于 k 1,我们可以显然发现必须满足 b[i] i,而…...

MySQL 8.0 OCP 英文题库解析(十)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题81~90 试题81:…...

不动产登记区块链系统(Vue3 + Go + Gin + Hyperledger Fabric)
好久没有介绍过新项目的制作了,之前做的一直都是Fisco Bcos的项目,没有介绍过Hyperledger Fabric的项目,这次来给大家分享下。 系统概述 不动产登记与交易平台是一个基于Hyperledger Fabric的综合性管理系统,旨在实现不动产登记…...