Linux 进程间通信(六)共享内存

2023-05-16

可以说, 共享内存是一种最为高效的进程间通信方式, 因为进程可以直接读写内存, 不需要任何数据的复制。 为了在多个进程间交换信息, 内核专门留出了一块内存区, 这段内存区可以由需要访问的进程将其映射到自己的私有地址空间。 因此, 进程就可以直接读写这一内存区而不需要进行数据的复制, 从而大大提高了效率。 当然, 由于多个进程共享一段内存,因此也需要依靠某种同步机制, 如互斥锁和信号量等(请参考 4.7.2 节)。

其原理示意图如图4.7 所示。
先参考这个博客:

共享内存的实现分为两个步骤:

第一步是创建共享内存, 这里用到的函数是 shmget(),也就是从内存中获得一段共享内存区域;

第二步是映射共享内存, 也就是把这段创建的共享内存映射到具体的进程空间中, 这里使用的函数是 shmat()。

到这里, 就可以使用这段共享内存了, 也就是可以使用不带缓冲的 I/O 读写命令对其进行操作。

除此之外, 还有撤销映射的操作, 其函数为 shmdt()。 这里主要介绍这 3 个函数。

在Linux中如何查看ipc对象如何删除ipc对象命令
 

ipcs -a:查看所有的ipc对象
ipcs -m:查看共享内存
ipcs -q:消息对列
ipcs -s:信号量

删除ipc对象命令:
ipcrm -m  SHM_ID 或ipcrm -M  shm_key
ipcrm -q  MSG_ID 或ipcrm -Q  msg_key
ipcrm -s  SEM_ID 或ipcrm -S  sem_key

 

shmget()函数的语法要点。

    函数原型

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

    功能

    创建获得共享内存

    函数传入值
    key: 共享内存的键值, 多个进程可以通过它访问同一个共享内存, 其中有个特殊值
    IPC_PRIVATE, 用于创建当前进程的私有共享内存
    size: 共享内存区大小
    shmflg: 同 open()函数的权限位, 也可以用八进制表示法
    函数返回值
    成功: 共享内存段标识符
    出错: 1

shmat()函数的语法要点。

    函数原型

    char *shmat(int shmid, const void *shmaddr, int shmflg)
    函数传入值
    shmid: 要映射的共享内存区标识符
    shmaddr: 将共享内存映射到指定地址(若为 0 则表示系统自动分配地址并把该段共享内存映射到调用进程的地址空间)
    shmflg:

        SHM_RDONLY: 共享内存只读
        默认 0: 共享内存可读写

    函数返回值
    成功: 被映射的段地址
    出错: 1

shmdt()函数的语法要点。

    函数原型
    int shmdt(const void *shmaddr)
    函数参数

    shmaddr: 被映射的共享内存段地址

    函数返回值
    成功: 0
    出错: 1

shmctl()函数的语法要点。

    函数原型

    int shmctl(int shmid, int cmd, struct shmid_ds *buf);

    功能

    对已存在的共享内存进行控制

    函数参数

    shmid:共享内存标识

    cmd:操作类型

    buf:指向操作的信息

    返回值

    成功返回0,否则返回-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;    /* 创建进程ID */
               pid_t           shm_lpid;    /* 最近操作的进程ID */
               shmatt_t        shm_nattch;  /* 建立映射的进程数 */
               ...
           };
struct ipc_perm {
               key_t          __key;    /* Key supplied to shmget(2) */
               uid_t          uid;      /* Effective UID of owner */
               gid_t          gid;      /* Effective GID of owner */
               uid_t          cuid;     /* Effective UID of creator */
               gid_t          cgid;     /* Effective GID of creator */
               unsigned short mode;     /* Permissions + SHM_DEST and
                                           SHM_LOCKED flags */
               unsigned short __seq;    /* Sequence number */
           };

实例代码:

发送端

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
 
#define N 64
 
typedef struct 
{
  pid_t pid;
  char buf[N];
}SHM;
 
void handler(int signo)
{
  //printf("get signal\n");
  return;
}
 
void keycontrol(int signo)
{
  printf("keycontrol is : %d\n",signo);
  if(signo == SIGINT)
  {
    return;
  }
}
 
int main()
{
  key_t key;
  int shmid;
  SHM *p;
  pid_t pid;
 
  //建立IPC通讯,获取key值
  if((key = ftok(".",'m')) < 0)
  {
    perror("fail to ftok");
    exit(-1);
  }
 
 
 
  signal(SIGUSR1,handler);
  signal(SIGINT,keycontrol); 
  // 创建共享内存
  if((shmid = shmget(key,sizeof(SHM),0666|IPC_CREAT|IPC_EXCL)) < 0)
  {//如果创建失败
    if(EEXIST == errno)//如果共享内存已经存在
    {
      shmid = shmget(key,sizeof(SHM),0666);//只是为了获得标识符
      p = (SHM *)shmat(shmid,NULL,0);
      pid = p->pid;
      p->pid = getpid();
      kill(pid,SIGUSR1);
    }
    else
    {
      perror("fail to shmget");
      exit(-1);
    }
  }
  else//如果创建成功
  {
    // 连接共享内存
    p = (SHM*)shmat(shmid,NULL,0);
    p->pid = getpid();
    pause();
    pid=p->pid;
  }
 
  printf("shmid = %d\n",shmid);
  while(1)
  {
    printf("write to shm:");
    fgets(p->buf,N,stdin);
    kill(pid,SIGUSR1);
    if(strcmp(p->buf,"quit\n")==0)
      break;
    pause();
  }
  // 断开连接
  shmdt(p);
  shmctl(shmid,IPC_RMID,NULL);
 
  return 0;
}

接收端

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
 
 
#define N 64
 
typedef struct 
{
  pid_t pid;
  char buf[N];
}SHM;
 
void handler(int signo)
{
  //printf("get signal\n");
  return;
}
 
int main()
{
  key_t key;
  int shmid;
  SHM *p;
  pid_t pid;
 
  // 获取key值
  if((key = ftok(".",'m')) < 0)
  {
    perror("fail to ftok");
    exit(-1);
  }
 
  signal(SIGUSR1,handler);
  // 创建共享内存
  if((shmid = shmget(key,sizeof(SHM),0666|IPC_CREAT|IPC_EXCL)) < 0)
  {//如果创建失败
    if(EEXIST == errno)//如果共享内存已经存在
    {
      shmid = shmget(key,sizeof(SHM),0666);//只是为了获得标识符
      p = (SHM *)shmat(shmid,NULL,0);
      pid = p->pid;
      p->pid = getpid();
      kill(pid,SIGUSR1);
    }
    else
    {
      perror("fail to shmget");
      exit(-1);
    }
  }
  else//如果创建成功
  {
    // 连接共享内存
    p = (SHM*)shmat(shmid,NULL,0);
    p->pid = getpid();
    pause();
    pid=p->pid;
  }
 
  while(1)
  {
    pause();
    if (strcmp(p->buf,"quit\n") == 0)
      exit(0);
    printf("read from shm:%s",p->buf);
    kill(pid,SIGUSR1);
  }
 
  return 0;
}

 


Linux 进程间通信(六)共享内存
https://blog.51cto.com/u_13267193/5371013

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 进程间通信(六)共享内存 的相关文章

  • R-Car H3系列SOC芯片与R-Car M3 R8A77961JBP0BA区别

    RENESAS推出的 xff1a R Car H3 系列 SOC 芯片 R8A77951JA00BA xff03 YJ1 xff0c R Car M3 系列 SOC 芯片 R8A77960JA60BG xff03 YJ5 在内核上 xff1
  • PTP(IEEE1588),TSN时间同步方法

    本文首先简要介绍主流的时间同步方式GNSS xff0c NTP xff0c PTP 然后通过NTP和PTP对比 xff0c 解释PTP性能更优秀的原因 xff1b 并对算法公式进行了推导 0 Why need time synchroniz
  • AUTOSAR的四种功能安全机制

    虽然AUTOSAR不是一个完整的安全解决方案 xff0c 但它提供了一些安全机制用于支持安全关键系统的开发 本文用于介绍AUTOSAR支持的四种功能安全机制 xff1a 内存分区 xff08 Memory Partitioning xff0
  • libstdc++版本冲突的解决

    类似的问题出现在测试环境部署过程 xff0c 当编译完成该前端解析器后 xff0c 由于其依赖一些库文件 xff0c 包括系统库文件libstdc 43 43 so 6 及 libc so xff0c 这都是系统至关重要的库文件 但是不同系
  • 3D打印——CLIP技术之更快速更高表面质量

    论文 Gradient light video projection based stereolithography for continuous production of solid objects 阅读 论文共分为6个章节 xff1a
  • 汽车上DTC是什么意思?DTC是什么故障

    DTC的全称是 Diagnostic Trouble Code xff0c 意为诊断故障代码 如今 xff0c 汽车很多故障都是通过故障代码去诊断的 xff0c 例如汽车底盘检测 车身及附件检测 汽车污染物与噪声处理部件等相关检测等 目的旨
  • 人生算法——读书笔记

    跨越出生和运气 xff0c 实现富足和自由 用概率思维 做好决策 人生算法九段 广义而言大自然有两个重要的算法 xff0c 一个是进化 xff0c 一个是大脑 现实中我们虽然拼命思考 xff0c 但是极少思考自己的思考 围绕认知的飞轮 xf
  • Linux 上功能强大的网络工具 tcpdump 详解

    tcpdump 是用于捕获传入和传出流量的网络实用程序 这是您需要了解的有关在 Linux 上使用 tcpdump 的所有信息 Linux 配备了大量的网络实用程序可供选择 tcpdump 是一种功能强大的网络工具 xff0c 如果您需要对
  • 简析车载以太网TSN标准

    众所周知 xff0c 通用以太网是以非同步方式工作的 xff0c 网络中任何设备都可以随时发送数据 xff0c 因此在数据的传输时间上既不精准也不确定 xff1b 同时 xff0c 广播数据或视频等大规模数据的传输 xff0c 也会因网络负
  • 英伟达发布的系统级芯片orin

    本文为英伟达全面分析的第七篇文章 xff0c 关注英伟达在今年会大规模交付的Orin系统级芯片 Orin 是亚特兰蒂斯神话第一任统治者 xff0c 海王Altan的儿子 Orin一经发布 xff0c 便成为众多车企争抢装车的对象 本文重点探
  • Shell内置命令之exit的语法与实例

    系统中是有exit命令的 用于退出当前用户的登录状态 但是在 Shell 脚本中 exit 语句是用来退出当前脚本的 下面这篇文章主要给大家介绍了关于Shell内置命令之exit的语法与实例 需要的朋友可以参考下 https www jb5
  • SHELL编程

    一 变量 1 shell 脚本基础知识 编译型语言 xff1a 如 c语言 解释型语言 xff1a shell 脚本 shell脚本的本质 xff1a shell命令的有序集合 2 shell 编程的基本过程 基本过程分为三步 xff1a
  • 浅谈TC8数据链路层测试

    当今时代 xff0c 智能汽车已成为一个炙手可热的话题 xff0c 各种先进汽车电子技术蓬勃发展 xff0c 比如自动驾驶 V2X OTA 这些新技术的背后都离不开车载以太网通信技术的支持 浅谈TC8数据链路层测试 知乎 其中数据链路层实现
  • 100 道 Linux 常见面试题 建议收藏,慢慢读~

    本文共 2W 43 字 xff0c 分别从 Linux 概述 磁盘 目录 文件 安全 语法级 实战 文件管理命令 文档编辑命令 磁盘管理命令 网络通讯命令 系统管理命令 备份压缩命令等方面拆解 Linux 常见面试问题 可以先收藏 xff0
  • patchelf 的功能以及使用 patchelf 修改 rpath 以解决动态库问题

    低版本 libc 库运行高版本 libc 库编译的程序 https blog csdn net Longyu wlz article details 108023117 在这篇博客中我描述了使用 patchelf 来修改动态库链接器的方法
  • Alpha-beta 算法

    Alpha beta 算法是棋类游戏中最常用的 xff0c 也是最基础的剪枝方法 xff0c 要说Alpha beta 算法 就得先说下max min博弈树 算法 xff0c 就是模拟电脑下子 xff0c 要下在对电脑最优的地方 xff0c
  • 关于SOME/IP的理解

    1 总体说明 如上图所示为标准的网络七层架构 xff0c SOME IP Scalable service Oriented MiddlewarE over IP xff0c 即 运行于IP之上的可伸缩的面向服务的中间件 他在系统中其实就是
  • Win10常用快捷键

  • 推荐3篇 如何建立自己的知识体系

    如何构建自己的知识体系 xff1f 看这一篇就够了 xff01 如何把学到的知识系统化 xff1f 怎么才能把知识系统化的学透彻呢 xff1f 这3步可以帮助你 什么是知识体系 xff1f 为什么要搭建知识体系 xff1f 如何搭建知识体系
  • 《富有的习惯》

    目录 关于作者 关于本书 核心内容 前言 第一部分 第二部分 习惯觉察表 结语 富人和穷人的区别是什么 xff1f 富人永远更谨慎 关于作者 本书作者是托马斯 科里 xff0c 他是一位美国著名的会计师和注册理财规划师 xff0c 开办了一

随机推荐

  • 演讲培训——荣耀时刻

    如何用惊艳的开场白引爆项目路演的全场 xff1f 如何用精准而生动的语言表达有力的商务主题 xff1f 如何层层递进环环相扣地展开内容 xff1f 如何打造激励人心激发行动的演讲结尾 xff1f 如何让观点有内在 xff0c 让语言有逻辑
  • QNX的调度算法

    作为一个硬实时操作系统 xff0c QNX是一个基于优先级抢占的系统 这也导致其基本调度算法相对比较简单 因为不需要像别的通用操作系统考虑一些复杂的 公平性 xff0c 只需要保证 优先级最高的线程最优先得到 CPU 就可以了 基本调度算法
  • 葡萄酒品酒的四个步骤

    第一步 xff1a 观色 将酒杯举到白色背景之上 xff0c 然后倾斜约45 xff0c 仔细观察酒液中心的颜色 边缘色泽 澄清度 通常而言 xff0c 红葡萄酒的越浅 xff0c 年份越老 xff1b 白葡萄酒的颜色越浅 xff0c 年份
  • 高通骁龙 8155 到底有什么魔力?

    高通骁龙8155采用安卓系统 xff0c 兼容性更好 xff0c APP的数量也就相当多 xff0c 硬件方面 xff0c 这颗芯片最高支持3个4K屏或4个2K屏 xff0c 4个麦克风6颗摄像头 xff0c 还有WiFi6 5G 蓝牙5
  • 当你遇到Bug该怎么办?

    一 问题复现 稳定复现问题才能正确的对问题进行定位 解决以及验证 一般来说 xff0c 越容易复现的问题越容易解决 1 1 模拟复现条件 有的问题存在于特定的条件下 xff0c 只需要模拟出现问题的条件即可复现 对于依赖外部输入的条件 xf
  • 增加远程访问用户

    http www zhuangjiba com hardware 34023 html http www zhuangjiba com hardware 34023 html 打开管理员权限 xff1a
  • 基于Java的“多功能五子棋”游戏的设计和实现

    源码地址 xff1a http download csdn net detail clx55555 9718406 下载或转载使用请声明原著 xff1a 但求心安 基于 Java的 多功能五子棋 游戏的设计和实现 引言 随着经济社会的迅速发
  • shell 脚本中的注释详解

    单行注释 xff1a 单行注释就比较简单了 xff0c 直接在行最前端加上符号 即可 具体用法如下所示 xff1a this is comment test echo 34 this is comment test 34 运行结果 xff1
  • 《演讲的本质》:如何做好一次公开演讲?

    关于本书 演讲的本质 是一本教你通过演讲最大化自己的影响力 建立信任关系的工具书 xff0c 探讨演讲的本质和价值 本书从视觉 听觉 语言三个角度来分析如何最大程度地打动听众 xff0c 并提供了行之有效的练习方法 核心内容 演讲的本质与价
  • ubuntu系统镜像下载源

    ubuntu 14 04 和16 04 快速下载 由于官网服务器在国外 xff0c 下载速度奇慢 xff0c 所以我们可以利用阿里云镜像下载ubuntu ubuntu 14 04 xff1a ubuntu releases 14 04安装包
  • 每天最重要的2小时

    关于作者 乔西 戴维斯 xff0c 他是哥伦比亚大学的心理学博士 xff0c 主要研究神经学领域 关于本书 从身体效能的角度 xff0c 让我们在面对一件事情时 xff0c 怎么才能把身体调整到一种巅峰状态 xff0c 进而对时间进行高效的
  • 【无标题】

    63张图 xff0c 一步一步带你弄清 Linux 虚拟内存管理 xff0c 厉害 内存管理子系统可谓是 Linux 内核众多子系统中最为复杂最为庞大的一个 xff0c 其中包含了众多繁杂的概念和原理 xff0c 通过内存管理这条主线我们把
  • 面试时不懂得自我介绍的人,最后都被PASS掉了

    做硬件维护的阿润最近后悔得直跳脚 在被公司赔偿清退后 xff0c 他直接开启了HIGH玩模式 xff0c 原计划先玩2个月再做面试准备 xff0c 结果冷不丁接到心仪公司的面试邀约 因为时间紧 邀约急 xff0c 在没做好充分准备的前提下
  • 开发板和电脑可以ping通但是ssh连接不上

    一 问题描述 某集群数据节点服务器频繁无法连接 xff0c 服务器间出现可ping通但ssh无法连接的情况 xff0c 使用带外地址登录后远程控制也无法显示正常界面 xff0c 重启后会短暂恢复 二 排查问题 重启服务器后检查服务器SSH状
  • 你对Linux下的实时性应该多点了解

    本文讲述一些有利于提高xenomai实时性的配置建议 xff0c 部分针对X86架构 xff0c 但它们的底层原理相通 xff0c 同样适用于其他CPU架构和系统 xff0c 希望对你有用 希望能够帮助大家 本文来自于微信公众号嵌入式Lin
  • 怎么保证ECU的“实时性”

    在最近一起有公开报道的辅助驾驶相关事故中 xff0c 由于AEB xff08 自动紧急制动系统 xff09 功能被怀疑没有起作用 xff0c 又有一家车企的高级辅助驾驶功能遭到质疑 其实 xff0c 目前大多数车辆中AEB功能的生效车速区间
  • 重磅成果丨ASAM SOVD 1.0.0正式发布

    重磅成果丨ASAM SOVD 1 0 0正式发布 测试行业动态 汽车测试网 编者寄语 xff1a 2022年6月底 xff0c ASAM SOVD 1 0 0版本正式发布 为了应对智能网联汽车时代井喷的软件诊断需求 xff0c SOVD如何
  • 2016-我在路上

    2016匆匆而过 xff0c 这一年做了很多 xff0c 也错过了很多 有些事情自己感觉很值得 xff0c 有些事情感觉很愧疚 xff0c 一年的酸甜苦辣尽在其中 寒假 xff0c 我加入的acm实验室 xff0c 有个集训 xff0c 但
  • 《复盘高手》

    今天为你介绍的是 复盘高手 xff0c 副标题是 自我认识与自我精进的底层逻辑 复盘 本是围棋的一个术语 xff0c 说的是下完一盘棋后 xff0c 棋手在棋盘上把下棋的过程复现一遍 xff0c 看看哪些地方下得好 xff0c 哪些地方不好
  • Linux 进程间通信(六)共享内存

    可以说 xff0c 共享内存是一种最为高效的进程间通信方式 xff0c 因为进程可以直接读写内存 xff0c 不需要任何数据的复制 为了在多个进程间交换信息 xff0c 内核专门留出了一块内存区 xff0c 这段内存区可以由需要访问的进程将