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

Liunx系统 : 进程间通信【IPC-Shm共享内存】

文章目录

  • System V
    • 共享内存
      • 创建共享内存
        • shmget
      • 控制共享内存
        • shmctl
    • shm特性

System V

System V是Liunx中的重要的进程间通信机制,它包括(shm共享内存,(msg消息队列和(sem信号量。本篇博客主要介绍其中最常用的一种方式–共享内存。


共享内存

顾名思义,共享内存是一块进程之间可以共享的内存区域,由于进程之间都是相互独立的,那么这块区域自然而然不是又某个进程开辟的,而应该是由操作系统亲自开辟。


在这里插入图片描述
如上图,共享内存会被进程的页表直接映射到自己的进程地址空间共享区,从而通过地址空间与页表直接访问到物理内存(可能有多层),进而对内存操作,这就是多个进程共享一块内存的基本原理。


创建共享内存

shmget

shmget 函数是 shm 中用于创建或获取共享内存段的函数。需要头文件<sys/ipc.h><sys/shm.h>函数原型如下:

int shmget(key_t key,size_t size,int shmflg)

返回值:

shmget返回一个整型,这个整型叫做shmid,用于标识唯一的shm

1.key : 标识要创建或获取的共享内存段,是System V方式的唯一标识。

注意和shmid区分,shmid是用来标识唯一的共享内存(shm)。

2.size : 指定要创建的共享内存段的大小,单位为字节

注意共享内存以4kb为基本单位开辟内存,因此开辟内存的时候,这个参数最好设置为4096的倍数,哪怕你只是申请了一个字节的内存,实际上还是会开辟4kb大小的空间的。

3 . shmflg : 用于指定共享内存段访问的权限和其他选项。

这是一个用于控制共享内存的开辟方式,以及各个属性的选项,本质上是一个位图。

  • IPC_CREAST : 如果指定的key不存在,则创建一个新的共享内存段,如果已经存在,则直接获取原先的共享内存。
  • IPC_EXCL:如果指定的key已经存在,则创建失败。

要注意IPC_EXCL只能配合IPC_CREAT一起使用,不能单独使用。

  • 还可以按照权限值的8进制位或到第三个参数之中。
int main()
{int shmid = shmget(1, 4096, IPC_CREAT | IPC_EXCL | 0666);return 0;
}

在这里插入图片描述

如果只想看共享内存的方式,则ipcs -m:
在这里插入图片描述

一开始存在一个shmid = 0的共享内存,之后通过指令的方式删除掉了这个共享方式,除了这种方式,我们还可以通过系统接口来删除共享内存,也就是下面要介绍的shmctl接口。


控制共享内存

shmctl

shmctl 用于控制共享内存的各种属性。

  1. 获取共享内存段的状态信息
  2. 修改共享内存段的属性
  3. 删除共享内存段

shmctl包含在头文件<sys/ipc.h><sys/shm.h>中,函数原型如下:

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 函数返回值

shmctl 函数的返回值用于指示操作是否成功:

  • 成功时:返回 0,表示操作已完成且未发生错误。
  • 失败时:返回 -1,并设置 errno 变量以指示具体的错误原因。常见的错误包括权限不足、无效的共享内存标识符等。

shmctl 函数有三个主要参数,它们共同决定了函数的行为:

  1. shmid:这是要操作的共享内存段的标识符。通过 shmget 函数可以获取该标识符,它是后续所有操作的基础,确保函数作用于正确的共享内存段。

  2. cmd:指定要执行的操作类型,它可以是以下值之一:

    • IPC_STAT:用于获取共享内存段的状态信息。此操作会将共享内存段的相关属性填充到由 buf 指向的 shmid_ds 结构体中,供程序查询和分析。
    • IPC_SET:用于设置共享内存段的某些属性。通过 buf 参数传递新的属性值,但需注意只有超级用户或拥有适当权限的进程才能执行此操作。
    • IPC_RMID:用于删除共享内存段。执行此操作后,共享内存段将被标记为可销毁,系统会在合适的时候将其从内核中移除。
  3. buf:这是一个指向 shmid_ds 结构体的指针。当 cmd 参数为 IPC_STAT 时,该结构体用于接收共享内存段的当前属性;当 cmd 参数为 IPC_SET 时,该结构体则包含需要设置的新属性值。

  • 相关结构体 shmid_ds

在使用 shmctl 函数时,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;   /* 最后更改时间 */pid_t           shm_cpid;    /* 创建者的 PID */pid_t           shm_lpid;    /* 最后调用 shmat/shmdt 的 PID */shmatt_t        shm_nattch;  /* 当前附加次数 */...
};

  • shm_perm:该字段是一个 ipc_perm 结构体,包含了共享内存段的所有者、组、权限等信息,用于控制进程对共享内存段的访问权限。
  • shm_segsz:表示共享内存段的大小,以字节为单位。在创建共享内存段时设置,后续操作中可通过 IPC_STAT 获取该值,或在有适当权限时通过 IPC_SET 修改。
  • 时间相关字段(shm_atime、shm_dtime、shm_ctime):分别记录了共享内存段最后被附加、分离以及更改的时间,这些信息对于监控共享内存段的使用情况非常有用。
  • 进程 ID 相关字段(shm_cpid、shm_lpid)shm_cpid 是创建共享内存段的进程的 PID,而 shm_lpid 是最后调用 shmatshmdt 函数的进程的 PID,有助于追踪共享内存段的使用历史。
  • shm_nattch:表示当前共享内存段被附加的次数。当进程调用 shmat 附加共享内存段时,该值会增加;当进程调用 shmdt 分离共享内存段时,该值会减少。当该值为 0 时,表示没有进程正在使用该共享内存段。

shmctl第二个参数cmdIPC_STAT,此时就可以获取一个共享内存的基本信息。

示例 :

int main()
{int id = shmget(1, 4096, IPC_CREAT | IPC_EXCL | 0666);struct shmid_ds shm;shmctl(id, IPC_STAT, &shm);cout << "atime:" << shm.shm_atime << endl;cout << "ctime:" << shm.shm_ctime << endl;cout << "cpid:" << shm.shm_cpid << endl;return 0;
}

在这里插入图片描述

第二个参数为IPC_SET时候可以设置共享内存的某些属性。

int main()
{int id = shmget(1, 4096, IPC_CREAT | IPC_EXCL | 0666);struct shmid_ds shm;shmctl(id, IPC_STAT, &shm);cout << "atime:" << shm.shm_atime << endl;//	140731859906331shm.shm_atime = 1 ;//修改shm信息shmctl(id, IPC_SET, &shm);//重新获取shm信息shmctl(id, IPC_STAT, &shm);cout << "atime:" << shm.shm_atime << endl;// 1return 0;
}

删除共享内存(通过接口的方式)


int main()
{shmctl(0, IPC_RMID, nullptr);return 0;
}

在这里插入图片描述

一开始存在一个shmid = 0 的共享内存,经过test之后,这个共享内存就被删除了。


上面我们详细讨论了如何来开辟一个共享内存,还没有真正使用这段共享内存来进行通信。

接下来,假设现在有AB两个进程,他们通过共享内存的方式进行通信,其中A负责发送消息,B负责接收消息。

A进程的代码数据如下:

int main()
{key_t key = ftok("./test.cpp", 1);int shmid = shmget(key, 4096, IPC_CREAT | IPC_EXCL | 0666);char* ptr = (char*)shmat(shmid, nullptr, 0);for(int ch = 'A'; ch <= 'Z'; ch++){ptr[ch - 'A'] = ch;sleep(1);}shmctl(shmid, IPC_RMID, nullptr);return 0;
}

B进程的代码数据如下:

int main()
{key_t key = ftok("./test.cpp", 1);int shmid = shmget(key, 4096, IPC_CREAT);char* ptr = (char*)shmat(shmid, nullptr, 0);while(true){cout << ptr << endl;sleep(5);}return 0;
}

在这里插入图片描述

可以看到A向共享内存中写入数据,就被B进程读到了


shm特性

共享内存有以下一些主要特性:

  1. 内存共享:多个进程可以同时访问和修改同一块共享内存区域。这种共享内存机制可以让进程之间高效地交换数据,而无需通过系统调用或者其他进程间通信机制。

  2. 快速访问:相比于其他进程间通信机制,如管道、消息队列等,共享内存的访问速度更快,因为数据直接存储在内存中,不需要进行数据的拷贝和上下文切换。

  3. 灵活性:共享内存可以在进程之间自由分配和管理,大小和位置都可以灵活设置。这种灵活性使得共享内存非常适合用于复杂的进程间通信场景。

  4. 同步问题:多个进程可以并发访问和修改共享内存,因此需要使用信号量、互斥锁等同步机制来协调对共享内存的访问,避免数据竞争和不一致性问题。

  5. 内存分配:共享内存是由内核管理的,进程无法直接分配和释放共享内存,必须通过系统调用如 shmget()shmctl() 来完成。


system V 的后两种通信方式 消息队列 msg信号量 sem 都非常不常用了,不深入研究。

相关文章:

Liunx系统 : 进程间通信【IPC-Shm共享内存】

文章目录 System V共享内存创建共享内存shmget 控制共享内存shmctl shm特性 System V System V是Liunx中的重要的进程间通信机制&#xff0c;它包括&#xff08;shm&#xff09;共享内存&#xff0c;&#xff08;msg&#xff09;消息队列和&#xff08;sem&#xff09;信号量。…...

KafkaRocketMQ

Kafka 消息生产与消费流程 1. 消息生产 生产者创建消息&#xff1a; 指定目标 Topic、Key&#xff08;可选&#xff09;、Value。可附加 Header 信息&#xff08;如时间戳、自定义元数据&#xff09;。 选择分区&#xff08;Partition&#xff09;&#xff1a; 若指定 Key&am…...

HarmonyOS Next 中的状态管理

在声明式UI编程框架中&#xff0c;UI是程序状态的运行结果&#xff0c;用户构建了一个UI模型&#xff0c;其中应用的运行时的状态是参数。当参数改变时&#xff0c;UI作为返回结果&#xff0c;也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染&#xff0c;在ArkU…...

基于qiime2的16S数据分析全流程:从导入数据到下游分析一条龙

目录 创建metadata 把数据导入qiime2 去除引物序列 双端合并 &#xff08;dada2不需要&#xff09; 质控 &#xff08;dada2不需要&#xff09; 使用deblur获得特征序列 使用dada2生成代表序列与特征表 物种鉴定 可视化物种鉴定结果 构建进化树&#xff08;ITS一般不构建进化树…...

【软件测试开发】:软件测试常用函数1.0(C++)

1. 元素的定位 web⾃动化测试的操作核⼼是能够找到⻚⾯对应的元素&#xff0c;然后才能对元素进⾏具体的操作。 常⻅的元素定位⽅式⾮常多&#xff0c;如id&#xff0c;classname&#xff0c;tagname&#xff0c;xpath&#xff0c;cssSelector 常⽤的主要由cssSelector和xpath…...

vue2项目修改浏览器显示的网页图标

1.准备一个新的图标文件&#xff0c;通常是. ico格式&#xff0c;也可以是. Png、. Svg等格式 2.将新的图标文件(例如&#xff1a;faviconAt.png)放入项目的public文件夹中。如下图 public文件夹中的所有文件都会在构建时原样复制到最终的输出目录(通常是dist) 3. 修改vue项目…...

开源、创新与人才发展:机器人产业的战略布局与稚晖君成功案例解析

目录 引言 一、开源&#xff1a;机器人产业的战略布局 促进技术进步和生态建设 吸引人才和合作伙伴 建立标准和网络效应 降低研发风险与成本 二、稚晖君&#xff1a;华为"天才少年计划"的成功典范 深厚的技术积累与动手能力 强烈的探索和创新意识 持续公开…...

线程相关作业

1.创建两个线程&#xff0c;分支线程1拷贝文件的前一部分&#xff0c;分支线程2拷贝文件的后一部分 #include "head.h"#define BUFFER_SIZE 1024// 线程参数结构体&#xff0c;包含文件名和文件偏移量 typedef struct {FILE *src_file;FILE *dest_file;long start_o…...

通义万相2.1开源版本地化部署攻略,生成视频再填利器

2025 年 2 月 25 日晚上 11&#xff1a;00 通义万相 2.1 开源发布&#xff0c;前两周太忙没空搞它&#xff0c;这个周末&#xff0c;也来本地化部署一个&#xff0c;体验生成效果如何&#xff0c;总的来说&#xff0c;它在国内文生视频、图生视频的行列处于领先位置&#xff0c…...

【模拟CMOS集成电路设计】带隙基准(Bandgap)设计与仿真(基于运放的电流模BGR)

【模拟CMOS集成电路设计】带隙基准&#xff08;Bandgap&#xff09;设计与仿真 前言工程文件&部分参数计算过程&#xff0c;私聊~ 一、 设计指标指标分析&#xff1a; 二、 电路分析三、 仿真3.1仿真电路图3.2仿真结果(1)运放增益(2)基准温度系数仿真(3)瞬态启动仿真(4)静态…...

如何选择国产串口屏?

目录 1、迪文 2、淘晶驰 3、广州大彩 4、金玺智控 5、欣瑞达 6、富莱新 7、冠显 8、有彩 串口屏&#xff0c;顾名思义&#xff0c;就是通过串口通信接口&#xff08;如RS232、RS485、TTL UART等&#xff09;与主控设备进行通信的显示屏。其核心功能是显示信息和接收输入…...

Solana中的程序派生地址(PDAs):是什么,为什么,以及如何?

程序派生地址 (PDA) 在 Solana 中的应用&#xff1a;什么、为什么和如何&#xff1f; 在学习 Solana 时&#xff0c;你会经常听到关于 程序派生地址 (PDAs) 的讨论。它们就像这样 —— 强大、多功能&#xff0c;而且最重要的是&#xff0c;稍微被误解。如果你是一个开发者&…...

利用FatJar彻底解决Jar包冲突(一)

利用FatJar彻底解决Jar包冲突 序FatJar的加载与隔离⼀、 FatJar概念⼆、FatJar的加载三、FatJar的隔离四、隔离机制验证五、 FatJar的定位六、 打包注意点 序 今天整理旧电脑里的资料&#xff0c;偶然翻到大概10年前实习时写的笔记&#xff0c;之前经常遇到Java依赖冲突的问题…...

Spring MVC笔记

01 什么是Spring MVC Spring MVC 是 Spring 框架中的一个核心模块&#xff0c;专门用于构建 Web 应用程序。它基于经典的 MVC 设计模式&#xff08;Model-View-Controller&#xff09;&#xff0c;但通过 Spring 的特性&#xff08;如依赖注入、注解驱动&#xff09;大幅简化了…...

BurpSuite插件jsEncrypter使用教程

一、前言 在当今Web应用安全测试中&#xff0c;前端加密已成为开发者保护敏感数据的常用手段。然而&#xff0c;这也给安全测试人员带来了挑战&#xff0c;传统的抓包方式难以获取明文数据&#xff0c;测试效率大打折扣。BurpSuite作为一款强大的Web安全测试工具&#xff0c;其…...

【C#实现手写Ollama服务交互,实现本地模型对话】

前言 C#手写Ollama服务交互&#xff0c;实现本地模型对话 最近使用C#调用OllamaSharpe库实现Ollama本地对话&#xff0c;然后思考着能否自己实现这个功能。经过一番查找&#xff0c;和查看OllamaSharpe源码发现确实可以。其实就是开启Ollama服务后&#xff0c;发送HTTP请求&a…...

Android Glide 框架线程管理模块原理的源码级别深入分析

一、引言 在现代的 Android 应用开发中&#xff0c;图片加载是一个常见且重要的功能。Glide 作为一款广泛使用的图片加载框架&#xff0c;以其高效、灵活和易用的特点受到了开发者的青睐。其中&#xff0c;线程管理模块是 Glide 框架中至关重要的一部分&#xff0c;它负责协调…...

每天记录一道Java面试题---day32

MySQL索引的数据结构、各自优劣 回答重点 B树&#xff1a;是一个平衡的多叉树&#xff0c;从根节点到每个叶子节点的高度差不超过1&#xff0c;而且同层级的节点间有指针相互连接。在B树上的常规检索&#xff0c;从根节点到叶子节点的搜索效率基本相当&#xff0c;不会出现大…...

Vue3 Pinia 符合直觉的Vue.js状态管理库

Pinia 符合直觉的Vue.js状态管理库 什么时候使用Pinia 当两个关系非常远的组件&#xff0c;要传递参数时使用Pinia组件的公共参数使用Pinia...

深度学习与大模型基础-向量

大家好&#xff01;今天我们来聊聊向量&#xff08;Vector&#xff09;。别被这个词吓到&#xff0c;其实向量在我们的生活中无处不在&#xff0c;只是我们没注意罢了。 1. 向量是什么&#xff1f; 简单来说&#xff0c;向量就是有大小和方向的量。比如你从家走到学校&#x…...

【网络编程】完成端口 IOCP

10.11 完成端口 10.11.1 基本概念 完成端口的全称是I/O 完成端口&#xff0c;英文为IOCP(I/O Completion Port) 。IOCP是一个异 步I/O 的 API, 可以高效地将I/O 事件通知给应用程序。与使用select() 或是其他异步方法不同 的是&#xff0c;一个套接字与一个完成端口关联了起来…...

《苍穹外卖》SpringBoot后端开发项目重点知识整理(DAY1 to DAY3)

目录 一、在本地部署并启动Nginx服务1. 解压Nginx压缩包2. 启动Nginx服务3. 验证Nginx是否启动成功&#xff1a; 二、导入接口文档1. 黑马程序员提供的YApi平台2. YApi Pro平台3. 推荐工具&#xff1a;Apifox 三、Swagger1. 常用注解1.1 Api与ApiModel1.2 ApiModelProperty与Ap…...

管理网络安全

防火墙在 Linux 系统安全中有哪些重要的作用&#xff1f; 防火墙作为网络安全的第一道防线&#xff0c;能够根据预设的规则&#xff0c;对进出系统的网络流量进行严格筛选。它可以阻止未经授权的外部访问&#xff0c;只允许符合规则的流量进入系统&#xff0c;从而保护系统免受…...

明日直播|Go IoT 开发平台,开启万物智联新征程

在物联网技术飞速发展的当下&#xff0c;物联网行业却深受协议碎片化、生态封闭、开发低效等难题的困扰。企业和开发者们渴望找到一个能突破这些困境&#xff0c;实现高效、便捷开发的有力工具。 3 月 11 日&#xff08;星期二&#xff09;19:00&#xff0c;GitCode 特别邀请独…...

系统架构设计师—系统架构设计篇—软件架构风格

文章目录 概述经典体系结构风格数据流风格批处理管道过滤器对比 调用/返回风格主程序/子程序面向对象架构风格层次架构风格 独立构件风格进程通信事件驱动的系统 虚拟机风格解释器基于规则的系统 仓库风格&#xff08;数据共享风格&#xff09;数据库系统黑板系统超文本系统 闭…...

【MySQL_04】数据库基本操作(用户管理--配置文件--远程连接--数据库信息查看、创建、删除)

文章目录 一、MySQL 用户管理1.1 用户管理1.11 mysql.user表详解1.12 添加用户1.13 修改用户权限1.14 删除用户1.15 密码问题 二、MySQL 配置文件2.1 配置文件位置2.2 配置文件结构2.3 常用配置参数 三、MySQL远程连接四、数据库的查看、创建、删除4.1 查看数据库4.2 创建、删除…...

【Zinx】Day5-Part4:Zinx 的连接属性设置

目录 Day5-Part4&#xff1a;Zinx 的连接属性设置给连接添加连接配置的接口连接属性方法的实现 测试 Zinx-v1.0总结 Day5-Part4&#xff1a;Zinx 的连接属性设置 在 Zinx 当中&#xff0c;我们使用 Server 来开启服务并监听指定的端口&#xff0c;当接收到来自客户端的连接请求…...

【英伟达AI论文】多模态大型语言模型的高效长视频理解

摘要&#xff1a;近年来&#xff0c;基于视频的多模态大型语言模型&#xff08;Video-LLMs&#xff09;通过将视频处理为图像帧序列&#xff0c;显著提升了视频理解能力。然而&#xff0c;许多现有方法在视觉主干网络中独立处理各帧&#xff0c;缺乏显式的时序建模&#xff0c;…...

小程序事件系统 —— 32 事件系统 - 事件分类以及阻止事件冒泡

在微信小程序中&#xff0c;事件分为 冒泡事件 和 非冒泡事件 &#xff1a; 冒泡事件&#xff1a;当一个组件的事件被触发后&#xff0c;该事件会向父节点传递&#xff1b;&#xff08;如果父节点中也绑定了一个事件&#xff0c;父节点事件也会被触发&#xff0c;也就是说子组…...

全球首款 5G-A 人形机器人发布

全球首款 5G-A 人形机器人于世界移动通信大会&#xff08;MWC2025&#xff09;上由中国移动、华为、乐聚联合发布。以下是关于这款机器人的详细介绍&#xff1a; 名称与背景 名称9&#xff1a;这款人形机器人名为 “夸父”&#xff0c;是中国移动、华为与乐聚机器人在 GTI 平台…...