共享内存-systemV

article/2025/6/21 11:02:24

01. 共享内存简述

共享内存是一个允许多个进程直接访问同一块物理内存区域的进程通信工具,因其本身不涉及用户态与核心态之间转换,故效率最佳。为了使用一个共享内存段,一般需要以下几个步骤:

  1. 调用shmget()创建一个新共享内存段或获取已有共享内存段的标识符。调用完成返回一个后续需要用到的共享内存标识符
  2. 调用shmat()用将shmid (shmget生成的)标识的共享内存段附加到调用进程的虚拟地址空间中
  3. 到此,程序可以将其与其他内存一样对待。shmat()系统调用会返回该段在虚拟地址空间的始址
  4. 调用shmdt()分离共享内存段,这样进厂将无法继续引用这段空间(可选)
  5. 调用shmctl()删除共享内存段,只有一个进程执行,当所有附加该段到虚拟地址空间的进程都分离之后才能将其销毁
进程1 内核 共享内存区 进程2 shmget(key, size, IPC_CREAT|0666) 返回 shmid shmat(shmid, NULL, 0) 返回内存指针 shm_ptr1 shmget(key, size, 0) 返回相同 shmid shmat(shmid, NULL, 0) 返回内存指针 shm_ptr2 创建物理内存段 写入数据 (e.g., sprintf(shm_ptr1, "Hello")) 读取数据 (e.g., printf("%s", shm_ptr2)) shmdt(shm_ptr1) shmdt(shm_ptr2) shmctl(shmid, IPC_RMID, NULL) 标记为待删除 当所有进程断开后 内核释放物理内存 进程1 内核 共享内存区 进程2

在这里插入图片描述


02. 共享内存接口

2.1 共享内存数据结构

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;  // 创建者PIDpid_t           shm_lpid;  // 最后操作PIDshmatt_t        shm_nattch;// 当前附加计数
};

2.2 生成键值key

       #include <sys/types.h>#include <sys/ipc.h>
//将`路径名`和`项目ID`转换成与之对应的`IPC`键值key_t ftok(const char *pathname, int proj_id);

**返回值:**蔡成功返回一个key_t值,失败返回-1

在这里插入图片描述


2.3 创建/获取共享内存段

       #include <sys/ipc.h>#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);

参数:

  • key:

    • IPC_PRIVATE(创建新内存)
    • 使用ftok() 生成的键值(用于进程间共享)
  • size:共享内存大小>0

  • shmflg

    • IPC_CREAT(不存在时创建)
    • IPC_EXCL(若存在则失败)
    • 权限位(如 0666

返回值:成功返回共享内存标识符 shmid,失败返回 -1

//part of code   
key_t key = ftok("../test", 'a');int shmid = shmget(key, 1024, IPC_CREAT | 0666);  // 不存在时创建   cout <<"shmid is:"<< shmid << endl;

在这里插入图片描述


2.4 连接共享内存

       #include <sys/types.h>#include <sys/shm.h>
//将共享内存段映射到进程的地址空间void *shmat(int shmid, const void *shmaddr, int shmflg);

参数:

  • shmid: 由shmget()返回的共享内存标识符
  • shmaddr:请求的附加地址:
    • NULL(由系统自动选择地址)
    • 显示指定(不推荐)
  • shmflg
    • SHM_RDONLY(只读)
    • SHM_REMAP(Linux下覆盖现有映射)
    • 0默认行为

返回值:成功返回共享内存的起始地址指针,失败返回 (void *) -1

//同一进程,没啥用  ,只是验证  
char*ptr=(char*)shmat(shmid, NULL, 0);sprintf(ptr, "Hello!");cout << ptr << endl;

2.5 控制共享内存

       #include <sys/ipc.h>#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid_ds *buf);

参数:

  • shmid:共享内存标识符

  • cmd(可选):

    • IPC_RMID(标记删除,最后一个进程分离后生效)
    • IPC_STAT(获取状态到 buf
    • IPC_SET(通过 buf 设置参数)
  • buf:用于存储或修改共享内存属性的结构体(cmd后两个选项)

返回值:成功返回0,失败返回 -1


2.6 分离共享内存

       #include <sys/types.h>#include <sys/shm.h>
//解除进程与共享内存段的映射关系int shmdt(const void *shmaddr);//0 success - failed

参数:

  • shmaddr:由shmat()返回的共享内存始址

返回值:成功返回0,失败返回 -1`

注: 分离一个共享内存段删除它是不同的。删除是通过shmctl()选项IPC_ RMID操作来完成的。


03. C/S简单通信

3.2 server.cpp

#include "comm.h"
int main(){key_t key = ftok(PATH_NAME, PROJ_ID);if(key < 0){perror("ftok");return 1;}int shmId = shmget(key, SIZE,IPC_CREAT | IPC_EXCL | 0666);//创建全新的shm,如果和系统已经存在ID冲突,就出错返回if(shmId < 0){perror("shmget");return 2;}printf("key->%u, shmId->%d\n", key, shmId);//sleep(1);char* mem = (char*)shmat(shmId, NULL, 0);//建立关联printf("attaches shm success\n");//sleep(15);//开始逻辑实现的部分while(1){sleep(1);printf("%s\n", mem);}  shmdt(mem);//去关联printf("detaches shm success\n");shmctl(shmId, IPC_RMID, NULL);//sleep(5);printf("key->0x%u, shmId->%d   shm delete success\n", key, shmId);//sleep(10);return 0;
}

3.2 client.c

#include "comm.h"
int main(){key_t key = ftok(PATH_NAME, PROJ_ID);if(key < 0){perror("ftok");return 1;}printf("%u\n",key);//client这里只需要获取即可int shmid = shmget(key, SIZE, IPC_CREAT);if(shmid < 0){perror("shmget");return 1;}char* mem = (char*)shmat(shmid, NULL, 0);//建立关联//sleep(5);printf("client process attaches success!\n");//这里是进行通信的部分char c = 'A';while(c <= 'Z'){mem[c - 'A'] = c;c++;mem[c - 'A'] = 0;sleep(2);}shmdt(mem);//移除关联//slee(5);  printf("client process detaches success!\n");return 0;
}

http://www.hkcw.cn/article/LDpLCRgQvS.shtml

相关文章

大语言模型值ollama使用(1)

ollama为本地调用大语言模型提供了便捷的方式。下面列举如何在windows系统中快捷调用ollama。 winR打开运行框&#xff0c;输入cmd 1、输入ollama list 显示已下载模型 2、输入ollama pull llama3 下载llama3模型 3、 输入 ollama run llama3 运行模型 4、其他 ollama li…

【基础算法】高精度(加、减、乘、除)

文章目录 什么是高精度1. 高精度加法解题思路代码实现 2. 高精度减法解题思路代码实现 3. 高精度乘法解题思路代码实现 4. 高精度除法 (高精度 / 低精度)解题思路代码实现 什么是高精度 我们平时使用加减乘除的时候都是直接使用 - * / 这些符号&#xff0c;前提是进行运算的数…

uni-data-picker级联选择器、fastadmin后端api

记录一个部门及部门人员选择的功能&#xff0c;效果如下&#xff1a; 组件用到了uni-ui的级联选择uni-data-picker 开发文档&#xff1a;uni-app官网 组件要求的数据格式如下&#xff1a; 后端使用的是fastadmin&#xff0c;需要用到fastadmin自带的tree类生成部门树 &#x…

MonitorSDK_性能监控(从Web Vital性能指标、PerformanceObserver API和具体代码实现)

性能监控 性能指标 在实现性能监控前&#xff0c;先了解Web Vitals涉及的常见的性能指标 Web Vitals 是由 Google 推出的网页用户体验衡量指标体系&#xff0c;旨在帮助开发者量化和优化网页在实际用户终端上的性能体验。Web Vitals 强调“以用户为中心”的度量&#xff0c;而…

Kubernetes架构与核心概念深度解析:Pod、Service与RBAC的奥秘

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言&#xff1a;云原生时代的操作系统 在云原生技术浪潮中&#xff0c;Kubernetes&#xff08;简称K8s&#xff09;已成为容器编排领域的"分布式操…

enumiax:IAX 协议用户名枚举器!全参数详细教程!Kali Linux教程!

简介 enumIAX 是一个 Inter Asterisk Exchange 协议用户名暴力枚举器。enumIAX 可以以两种不同的模式运行&#xff1b;顺序用户名猜测或字典攻击。 enumIAX 可以以两种不同的模式运行&#xff1a;顺序用户名猜测或字典攻击。 顺序用户名猜测 在顺序用户名猜测模式下&#xf…

《深入解析SPI协议及其FPGA高效实现》-- 第一篇:SPI协议基础与工作机制

第一篇&#xff1a;SPI协议基础与工作机制 1. 串行外设接口导论 1.1 SPI的核心定位 协议本质 &#xff1a; 全双工同步串行协议&#xff08;对比UART异步、IC半双工&#xff09;核心优势 &#xff1a; 无寻址开销&#xff08;通过片选直连&#xff09;时钟速率可达100MHz&…

C++语法系列之模板进阶

前言 本次会介绍一下非类型模板参数、模板的特化(特例化)和模板的可变参数&#xff0c;不是最开始学的模板 一、非类型模板参数 字面意思,比如&#xff1a; template<size_t N 10> 或者 template<class T,size_t N 10>比如&#xff1a;静态栈就可以用到&#…

STL-list

1.list概述 List 并非 vector 与 string 那样连续的内存空间&#xff0c;list 每次插入或删除一个元素&#xff0c;都会新配置或释放一个元素的空间&#xff0c;所以list对于空间的使用很充分&#xff0c;一点也没有浪费&#xff0c;对于任意位置的插入或删除元素&#xff0c;时…

导入Maven项目

目录 5. 5.1 导入方法1 5.2 导入方法2 5.1 导入方法1 建议选择pom.xml文件导入 导入成功 5.2 导入方法2 导入成功

【含文档+PPT+源码】基于微信小程序的社区便民防诈宣传系统设计与实现

项目介绍 本课程演示的是一款基于微信小程序的社区便民防诈宣传系统设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套…

【Unity笔记】Unity WASD+QE 控制角色移动与转向(含 Shift 加速)实现教程

摘要&#xff1a; 在 Unity 游戏开发中&#xff0c;键盘控制角色的移动与转向是基础功能之一。本文详细讲解如何使用 C# 实现基于 WASD 移动、QE 转向 与 Shift 加速奔跑 的角色控制器&#xff0c;适用于第一人称、第三人称、自由漫游等场景。通过直观的 Transform 控制方法与可…

通讯方式学习——单总线协议(2024.04.09)

参考链接1: 单总线器件DS18B20测温程序该怎么编写&#xff1f;这个视进行了详细讲解&#xff01; 在此感谢各位前辈大佬的总结&#xff0c;写这个只是为了记录学习大佬资料的过程&#xff0c;内容基本都是搬运的大佬博客&#xff0c;觉着有用自己搞过来自己记一下&#xff0c;如…

大语言模型(LLM)入门 - (1) 相关概念

文章来自&#xff1a;大语言模型(LLM)小白入门自学项目-TiaoYu-1 GitHub - tiaoyu1122/TiaoYu-1: For People! For Freedom!For People! For Freedom! Contribute to tiaoyu1122/TiaoYu-1 development by creating an account on GitHub.https://github.com/tiaoyu1122/TiaoYu…

[9-3] 串口发送串口发送+接收 江协科技学习笔记(26个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26中断

【Linux系列】Linux/Unix 系统中的 CPU 使用率

博客目录 多核处理器时代的 CPU 使用率计算为什么要这样设计&#xff1f; 解读实际案例&#xff1a;268.76%的 CPU 使用率性能分析的意义 相关工具与监控实践1. top 命令2. htop 命令3. mpstat 命令4. sar 命令 实际应用场景容量规划性能调优故障诊断 深入理解&#xff1a;CPU …

内存管理 : 04段页结合的实际内存管理

一、课程核心主题引入 这一讲&#xff0c;我要给大家讲的是真正的内存管理&#xff0c;也就是段和页结合在一起的内存管理方式。之前提到过&#xff0c;我们先学习了分段管理内存的工作原理&#xff0c;知道操作系统采用分段的方式&#xff0c;让用户程序能以分段的结构进行编…

MCP Python技术实践

目录 1. 引言篇 1.1 什么是MCP&#xff08;Model Context Protocol&#xff09; 1.2 MCP的核心设计理念​ 1.3 MCP的技术背景 1.3 学习目标与内容概览 2. 基础理论篇 2.1 MCP协议架构详解 2.2 MCP消息格式与通信机制 2.3 MCP核心概念深入 3. 环境搭建篇 3.1 开发环境…

《数据结构初阶》【番外篇:二路归并的外排史诗】

【番外篇&#xff1a;多路归并的外排史诗】目录 前言&#xff1a;---------------介绍---------------一、实际情景二、外部排序什么是外部排序&#xff1f; 三、多路归并排序什么是多路归并排序&#xff1f; ---------------实现---------------四、文件归并文件二路归并排序思…

【JavaEE】多线程

5.线程启动&#xff08;statrt方法&#xff09; start方法内部&#xff0c;会调用系统api来在系统内核中创建出线程&#xff0c;创建完线程后会自动调用run方法。 而run方法&#xff0c;就只是描述这个线程要执行的任务。 start 和 run 得区别&#xff08;经典面试题&#xf…