《Linux系统编程篇》共享内存(Linux 进程间通信(IPC))——基础篇
文章目录
- 引言
- 什么是共享内存
- System V 共享内存 API 引入
- 1. `shmget`
- 2. `shmat`
- 3. `shmdt`
- 4. `shmctl`
- 5. 结构体 `shmid_ds`
- 开始实操
- 注意
- 结束
今天的你有没有前进一小步呢
——家驹(StrangeHead)
引言
那么共享内存,我们如何去使用他呢,先来听笔者啰嗦一段话吧!有个整体的概念。
共享内存,听这个名字就像已经知道他是什么东东了,既然我们现在学习的的Linux进程之间的通讯,所以这个共享内存肯定也离不开通讯的功能,是的,他是IPC中的重要一员,成为高手,也是必须要掌握的。
对于共享内存,Linux中共享内存的两种主要实现方式:System V和POSIX。没错又是两套API,关于这两套API,笔者就教大家如何使用System V吧,因为POSIX感觉并不常用,读者朋友们有兴趣可以自己学一学。
那么进入正题。
什么是共享内存
他总体的作用就是,在Linux当中开辟一段内存空间,使得两个进程可以同时访问,是的就是这么简单
具体操作可以具象为操作一个文件(毕竟Linux中一切皆是文件呢)
open一个文件(没有就创建他)
我可以使用read读取他,也可以使用write去修改他。
当然这个文件,也可以让所有进程看到,并操作。
这样说,我们理所当然的就学会了共享内存,我们对于一个文件的操作,其实就是对共享内存进行操作!
那么他有什么API呢,总不能和文件的open等等的API冲突吧,肯定也有自己的优势,方便之处吧,来看一下吧。
特性 | 共享内存 | 文件操作 |
---|---|---|
速度 | 直接在内存中操作,速度快 | 涉及磁盘 I/O,速度较慢 |
内存共享 | 多个进程可以直接共享数据 | 每个进程通常创建自己的文件副本 |
资源利用 | 内存使用更加高效,避免冗余 | 每个进程可能会重复打开和关闭文件 |
数据一致性 | 直接访问最新数据,避免不一致性 | 可能需要额外同步机制保证一致性 |
适用场景 | 高频率、大量数据交换 | 持久化存储、日志记录等 |
复杂性 | 需要管理访问权限和同步机制 | 操作相对简单,易于理解 |
系统调用数量 | 包含 shmget , shmat , shmdt , shmctl | 包含 open , read , write , close |
- 共享内存 更适合需要快速、高效的数据交换的场景,尤其是涉及到大量数据的实时处理。
- 文件操作 更适合需要持久化存储和简单文件操作的场景。
查看和删除共享内存(拓展)
你可以使用ipcs -m
查看共享内存段,并通过ipcrm
删除它
System V 共享内存 API 引入
总之就是下面这一坨了
int shmget(key_t key, size_t size, int shmflg); // 创建/获取共享内存
void *shmat(int shmid, const void *shmaddr, int shmflg); // 附加到进程空间
int shmdt(const void *shmaddr); // 分离共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf); // 控制操作
我们依次介绍他。大致看看即可,通过实例学习,不了解可以回来继续复习。🎯
1. shmget
功能:创建一个新的共享内存段或者获取一个已经存在的共享内存段的标识符。
原型:
int shmget(key_t key, size_t size, int shmflg);
参数:
key
:用于标识共享内存段的键。可以通过ftok
函数生成一个唯一的键。size
:共享内存段的大小(以字节为单位)。如果要创建新的共享内存段,此值必须大于 0。shmflg
:控制标志,可以包括以下选项:IPC_CREAT
:如果指定的共享内存段不存在,则创建它。IPC_EXCL
:与IPC_CREAT
一起使用,如果共享内存段已经存在,则调用失败。- 权限标志(如
0666
)指定谁可以读/写共享内存段。
返回值:成功时返回共享内存段的标识符(非负整数),失败时返回 -1,并设置 errno
。
示例:
int shm_id = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666);
2. shmat
功能:将共享内存段附加到调用进程的地址空间。
原型:
void* shmat(int shm_id, const void* shmaddr, int shmflg);
参数:
shm_id
:通过shmget
返回的共享内存段标识符。shmaddr
:希望共享内存段附加到的地址。通常可以设置为NULL
,由系统自动选择。shmflg
:控制标志,通常设置为 0。
返回值:成功时返回指向共享内存段的指针,失败时返回 (void*) -1,并设置 errno
。
示例:
char* shm_ptr = (char*) shmat(shm_id, NULL, 0);
3. shmdt
功能:将共享内存段从调用进程的地址空间分离。
原型:
int shmdt(const void* shmaddr);
参数:
shmaddr
:指向之前通过shmat
返回的共享内存指针。
返回值:成功时返回 0,失败时返回 -1,并设置 errno
。
示例:
if (shmdt(shm_ptr) == -1) {perror("shmdt failed");
}
4. shmctl
功能:控制共享内存段的操作,包括查询、修改和删除。
原型:
int shmctl(int shm_id, int cmd, struct shmid_ds* buf);
参数:
shm_id
:共享内存段的标识符。cmd
:控制命令,可以是以下之一:IPC_STAT
:填充shmid_ds
结构体(用于获取共享内存信息)。IPC_RMID
:标记共享内存段为待删除。IPC_SET
:修改共享内存段的权限和其他信息(需要提供相应的shmid_ds
结构体)。IPC_INFO
:获取系统共享内存的信息(通常是系统级的)。
buf
:指向shmid_ds
结构体的指针,用于输入/输出的控制信息。
返回值:成功时返回 0,失败时返回 -1,并设置 errno
。
示例(删除共享内存段):
if (shmctl(shm_id, IPC_RMID, NULL) == -1) {perror("shmctl IPC_RMID failed");
}
5. 结构体 shmid_ds
用于描述共享内存段的状态,包括以下字段:
struct shmid_ds {struct ipc_perm shm_perm; // 共享内存的权限size_t shm_segsz; // 共享内存段的大小time_t shm_atime; // 最后附加时间time_t shm_dtime; // 最后分离时间time_t shm_ctime; // 最后控制时间unsigned short shm_cpid; // 创建该共享内存段的进程 IDunsigned short shm_lpid; // 最后操作该共享内存段的进程 IDshort shm_nattch; // 当前附加到该共享内存段的进程数
};
开始实操
通过上述 API,可以有效地创建和管理共享内存段,从而实现进程间的高效通信。在使用共享内存时,务必注意同步问题,以避免数据竞争和不一致性。对于更复杂的应用,可能需要结合其他 IPC 机制(如信号量)来实现更可靠的进程间通信。
我们先简单的利用API来实现两个程序,一个写入,一个读取。
写入进程:
#include <sys/ipc.h>
#include <sys/shm.h>#define SHM_SIZE 1024int main() {key_t key = ftok("shmfile", 65);int shmid = shmget(key, SHM_SIZE, 0666|IPC_CREAT);char *str = (char*) shmat(shmid, NULL, 0);sprintf(str, "Hello from PID %d", getpid());shmdt(str);return 0;
}
读取进程:
// ...(头文件同上)
int main() {key_t key = ftok("shmfile", 65);int shmid = shmget(key, SHM_SIZE, 0666);char *str = (char*) shmat(shmid, NULL, 0);printf("Received: %s\n", str);shmdt(str);shmctl(shmid, IPC_RMID, NULL); // 删除共享段return 0;
}
这里仅仅做了这样一个小实验,随着日后,技术的提升,不断迭代,希望读者可以灵活应用,这里没有加入其它IPC同步机制,实际使用,对于共享内存的访问是要做保护机制的!!!仅仅让读者快速掌握他如何使用。
监控与调试技巧 使用ipcs -m查看System V共享段
通过lsof /dev/shm检查POSIX对象
分析/proc/sysvipc/shm获取详细信息
使用strace跟踪shm相关系统调用
注意
同步机制(必须实现以下之一):
使用共享内存必须必须使用同步机制,避免同时访问或者操作,造成数据错乱或者死机
-
信号量(semaphore)
-
互斥锁(pthread_mutex,需配置进程共享属性)
-
文件锁(fcntl)
生命周期管理:
-
System V:需主动调用shmctl(IPC_RMID)
-
POSIX:引用计数归零后自动删除
安全配置:
-
严格设置权限位(如0600)
-
避免使用可预测的IPC键值
-
及时清理未使用的共享段
性能调优:
-
使用大页内存(Hugepages)
-
对齐内存访问边界
-
避免频繁attach/detach操作
结束
浅浅的总结一下吧,这节我们学到了System V共享内存,以及他的一些核心API的使用,知道了他是什么东西。虽然操作文件的大致流程上没有俩样。但是使用上还是更具实际情况选择哦,并且给了两段小程序来帮助理解,再次提醒,实际情况,要做同步机制保护。
好了,本文就到这里了,让我们每天进步一小步吧!
相关文章:
《Linux系统编程篇》共享内存(Linux 进程间通信(IPC))——基础篇
文章目录 引言什么是共享内存System V 共享内存 API 引入1. shmget2. shmat3. shmdt4. shmctl5. 结构体 shmid_ds 开始实操注意 结束 今天的你有没有前进一小步呢 ——家驹(StrangeHead) 引言 那么共享内存,我们如何去使用他呢,先来听笔者啰嗦一段话吧…...

【EB-03】 AUTOSAR builder与EB RTE集成
AUTOSAR builder与EB RTE集成 1. Import Arxml files to Tresos2. Run MultiTask Script3. Add Components3.1 Run EcuExtractCreator Script4. Mapping Component to Partitions5. Event Mapping/Runnables Mapping to Tasks6. Port Connect7. Run SvcAs_Trigger Script8. Ver…...

HTML——前端基础1
目录 前端概述 前端能做的事情编辑 两步完成一个网页程序 前端工具的选择与安装 HTML HTML5介绍 HTML5的DOCTYPE声明 HTML基本骨架 文字标签 标题之标签 标签之段落、换行、水平线 标签之图片 标签之超文本链接 标签之文本 列表标签之有序列表 列表标签之无序…...
AI回答:Linux C/C++编程学习路线
Linux C/C编程学习路线需要结合Linux系统特性和C/C语言的特点,以下是一个系统化的学习路径,适合从初学者到进阶者: 第一阶段:Linux基础 Linux操作系统基础 学习Linux基本命令:ls、cd、mkdir、rm、grep、find等。 理解…...
螺旋数字矩阵
螺旋数字矩阵 真题目录: 点击去查看 E 卷 100分题型 题目描述 疫情期间,小明隔离在家,百无聊赖,在纸上写数字玩。他发明了一种写法: 给出数字个数n和行数m(0 < n ≤ 999,0 < m ≤ 999),从左上角的1开始,按照顺时针螺旋向内写方式,依次写出2,3…n,最终形成一…...

Jupyter Notebook切换虚拟环境(Kernel管理)
我们在使用Jupyter Notebook的时候,打开文件发现只有一个Python3(ipykernel),我们自己在conda中创建的虚拟环境为什么没有显示出来,今天我就来和大家一起讨论一下! 在 Jupyter Notebook 中,kernel 是执行代码的核心。管…...
linux下软件安装、查找、卸载
目录 常见安装方式有三种: 1.源码安装。 2.rpm安装方式。 3.yum/apt工具级别安装。 对于前两种安装方式,因为软件可能有依赖关系(安装的软件依赖于某些库,而这些库又依赖于某些库,这些都需要手动安装)…...
vuetify项目添加代理跨域请求
vuetify项目添加代理转发后端接口实现跨域请求 配置一(推荐)配置二 在项目根目录下找到vite.config.mts文件并在里面的server下配置代理, 具体实现代码如下: 配置一(推荐) server: {port: 3000,// 配置代理…...

H5 火柴人科目三和GitHub获取仓库点星星的用户列表发生了艺术的碰撞
先看效果,代码写的比较乱,有待优化 效果 https://linyisonger.github.io/H5.Examples/?name./089.%E7%9C%8B%E6%98%9F%E6%98%9F%E7%9A%84%E8%88%9E%E8%80%85.html 思路 看起来很简单,实则也不是很难,就是需要思路要打开。 一…...

【Azure 架构师学习笔记】- Azure Databricks (12) -- Medallion Architecture简介
本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (11) – UC搭建 前言 使用ADB 或者数据湖,基本上绕不开一个架构“Medallion”, 它使得数据管理更为简单有效。ADB 通过…...
基础知识|原型在什么时候用和类的区别
在 JavaScript 中,原型和类是两个密切相关但有所不同的概念。理解这两者之间的差异有助于更好地掌握面向对象编程(OOP)在 JavaScript 中的实现。 1. 原型(Prototype) 原型是 JavaScript 中实现继承和共享行为的核心机…...
【FFmpeg】拉流
概述 项目实践中涉及到使用ffmpeg进行推流和拉流操作,本文主要对一些基本操作做一个学习总结,后续再学习其源码架构;总结方法遵循实现功能配合函数具体实现 基本使用 拉流 avformat_network_init();//日志输出等级set_ffmpeg_log_level();…...

LangChain构建行业知识库实践:从架构设计到生产部署全指南
文章目录 引言:行业知识库的进化挑战一、系统架构设计1.1 核心组件拓扑1.2 模块化设计原则二、关键技术实现2.1 文档预处理流水线2.2 混合检索增强三、领域适配优化3.1 医学知识图谱融合3.2 检索结果重排序算法四、生产环境部署4.1 性能优化方案4.2 安全防护体系五、评估与调优…...

解决jupyter notebook不是内部或外部命令问题
我们打开cmd有的时候,输入jupyter notebook,发现会提示jupyter 不是内部或外部命令,也不是可运行的程序或批处理文件。遇到这个问题我们应该怎么解决呢? 没错就是添加环境变量! Step01:在电脑中找到jupyter notebook的…...
MySQL----case的用法
在 MySQL 中,CASE 表达式是一个用于条件判断的功能,可以根据不同的条件返回不同的结果。CASE 表达式通常用于 SELECT 查询语句中,可以在 SQL 中灵活地进行条件判断和数据转换。CASE 有两种基本的语法形式: 简单 CASE 表达式&…...

Unity XR-XR Interaction Toolkit开发使用方法(十)组件介绍(XR Interaction Group)
目录 一、插件介绍 二、主要组件 XR Interaction Manager XR Controller XR Interactor XR Direct Interactor XR Ray Interactor XR Socket Interactor XR Gaze Interactor 三、XR Interaction Group 1、组件介绍 2、核心功能与特点 优先级与冲突管理 动态交互切…...

深入理解 并查集LRUCaChe
并查集&LRUCaChe 个人主页:顾漂亮 文章专栏:Java数据结构 1.并查集的原理 在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后根据一定规律将归于同一组元素的…...
详解 c++ 中的 namespage
C 中的命名空间很特别,其他编程语言基本都没有。命名空间介于函数与类之间,兼顾了二者的一些优点。这篇博客根据 chatgpt 的回答整理。 文章目录 **1. 什么是 namespace(命名空间)?****2. 语法****3. 使用 namespace 访…...
50周学习go语言:第五周 复合类型与词频统计
以下是第五周复合类型(数组、切片与映射)的详细学习内容,按照第四周的深度要求设计: 第五周:复合类型与词频统计 一、复合类型详解 1. 数组(Array) // 声明与初始化 var arr1 [3]int …...
HTTP非流式请求 vs HTTP流式请求
文章目录 HTTP 非流式请求 vs 流式请求一、核心区别 服务端代码示例(Node.js/Express)非流式请求处理流式请求处理 客户端请求示例非流式请求(浏览器fetch)流式请求处理(浏览器fetch) Python客户端示例&…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...