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

目录

system V共享内存

​编辑

共享内存函数

共享内存的建立过程

shmget函数

shmctl函数

shmat函数

shmdt函数

实例代码

共享内存的特点


system V共享内存

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间(即内存通过某种映射关系连接到了进程使得进程能够访问这段内存),这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。

共享内存函数

我们之前的文章介绍的管道通信本质是基于文件的,OS没有做过多的设计工作。

而system V进程间通信是OS特地设计的通信方式,是为了想尽一切办法让不同的进程看到同一份资源。(具体的方法就是将物理内存映射到进程的地址空间中,本质就是修改页表,在虚拟地址空间中开辟空间,用的是系统调用接口)

共享内存的建立过程

1、申请共享内存

2、共享内存挂接到地址空间

3、去关联共享内存

4、释放共享内存

前两点式通信过程,后两点是释放资源的过程

shmget函数

功能:用来创建共享内存

原型

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

参数

        key:这个共享内存段名字

        size:共享内存大小

        shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样                          的

返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1

 //comm.h                                                                                                                                                                                     
  1 #ifndef _COMM_H_ 
  2 #define _ COMM_H_
  3 #include <stdio.h>
  4 #include <sys/types.h>
  5 #include <sys/ipc.h>
  6 #include <sys/shm.h>
  7 
  8 #define PATHNAME "."
  9 #define PROJ_ID 0x6666
 10 #define SIZE 4096
 11 
 12 #endif                                                                                                                                                                                                       

    //sever.c
    1 #include "comm.h"
    2 #include <unistd.h>
    3 int main()
    4 {
    5   key_t k = ftok(PATHNAME, PROJ_ID);
    6   if(k < 0)
    7   {
    8     perror("ftok");
    9     return 1;
   10   }
   11   printf("%x\n", k);
   12   int shmid = shmget(k, SIZE, IPC_CREAT|IPC_EXCL|0644);
   13   if(shmid < 0)
   14   {
   15     perror("shmget");
   16     return 2;
   17   }
   18  
   19   return 0;
   20 }

运行这一段代码,便能成功创建一块共享内存,可以使用ipcs -m命令查看

shm的生命周期是随内核的,进程不主动删除或者用命令删除,共享内存就一直存在,直到关机重启。

释放这一块空间则是用命名ipcrm -m [shmid]

当然这块内存的释放也有函数可以使用,没必要在命令行进行这么麻烦的操作

shmctl函数

功能:用于控制共享内存

原型

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

参数

        shmid:由shmget返回的共享内存标识码

        cmd:将要采取的动作(有三个可取值)

        buf:指向一个保存着共享内存的模式状态和访问权限的数据结构

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

在上面创建的server.c中结尾加上这一段


   sleep(10);
   shmctl(shm, IPC_RMID, NULL);
   sleep(10);    

运行这一段代码,可以看到共享内存一开始被创建,然后过了一会就被删除了

至此我们就完成了共享内存的创建与释放,那么接下来要解决的问题就是如何进行映射了

shmat函数

功能:将共享内存段连接到进程地址空间

原型

        void *shmat(int shmid, const void *shmaddr, int shmflg);

参数

        shmid:共享内存标识

        shmaddr:指定连接的地址

        shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY

返回值:成功返回一个指针,指向共享内存的第一个节;失败返回-1

    1 #include "comm.h"
    2 #include <unistd.h>
    3 #include <string.h>
    4 #include <sys/types.h>
    5 #include <sys/ipc.h>
    6 #include <sys/shm.h>
    7 int main()
    8 {
    9   key_t _key = ftok(PATHNAME, PROJ_ID);
   10   if(_key < 0)
   11   {
   12     perror("ftok");
   13     return -1;
   14   }
   15   printf("%x\n",_key);
   16   int shmid = 0;
   17   if((shmid = shmget(_key, SIZE, IPC_CREAT|IPC_EXCL|0644)) < 0)
   18   {
   19     perror("shmget");
   20     return -2;
   21   }
   22 
   23   printf("shmid: %d\n", shmid);
   24 
   25   printf("attach begin!\n");
   26   sleep(3);
   27   char* mem = shmat(shmid, NULL, 0);
   28   if(mem == (void*)-1)
   29   {
   30     perror("shmat");
   31     return 3;
   32   }                                                                                             
   33   printf("attach end!\n");
   34   sleep(3);
   35 
   36   shmctl(shmid, IPC_RMID, NULL);
   37 
   38   return 0;
   39 }

说明:

shmaddr为NULL,核心自动选择一个地址

shmaddr不为NULL且shmflg无SHM_RND标识,则以shmaddr为连接地址

shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHML BA的整数倍。公式:shmaddr - (shmaddr % SHML BA)

shmflg=SHM_RDONLY,表示连接操作用来只读共享内存

shmdt函数

功能:将共享内存段与当前进程脱离

原型

        int shmdt(const void *shmaddr);

参数

        shmaddr:由shmat所返回的指针

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

注意:将共享内存段与当前进程脱离不等于删除共享内存段

取消关联即在上面那段代码中的释放共享内存前加入

shmdt(mem);

即可取消进程与共享内存间的关联

实例代码
//comm.h
  1 #ifndef _COMM_H_ 
  2 #define _ COMM_H_
  3 #include <stdio.h>
  4 #include <sys/types.h>
  5 #include <sys/ipc.h>
  6 #include <sys/shm.h>
  7 
  8 #define PATHNAME "."
  9 #define PROJ_ID 0x6666
 10 #define SIZE 4096
 11 
 12 #endif        
//server.c
    1 #include "comm.h"
    2 #include <unistd.h>
    3 int main()
    4 {
    5   key_t k = ftok(PATHNAME, PROJ_ID);
    6   if(k < 0)
    7   {
    8     perror("ftok");
    9     return 1;
   10   }
   11   printf("%x\n", k);
   12   int shmid = shmget(k, SIZE, IPC_CREAT|IPC_EXCL|0644);
   13   if(shmid < 0)
   14   {
   15     perror("shmget");
   16     return 2;
   17   }
   18 
   19   printf("shmid: %d\n", shmid);
   20 
   21   sleep(5);
   22   char* mem = shmat(shmid, NULL, 0);
   23   while(1)
   24   {
   25   printf("client msg# %s\n", mem);
   26   sleep(1);                                                                                     
   27   }
   28   shmdt(mem);
   29 
   30   shmctl(shmid, IPC_RMID, NULL);
   31 
   32   return 0;
   33 }
   34 
//client.c
    1 #include "comm.h"
    2 #include <unistd.h>
    3 #include <string.h>
    4 int main()
    5 {
    6   key_t k = ftok(PATHNAME, PROJ_ID);
    7   if(k < 0)
    8   {
    9     perror("ftor");
   10     return 1;
   11   }
   12   int shmid = shmget(k, SIZE,0644);
   13   if(shmid < 0)
   14   {
   15     perror("shmget");
   16     return 2;
   17   }
   18 
   19   char* mem = shmat(shmid, NULL, 0);
   20 
   21   int i = 0;                                                                                    
   22   while(1)
   23   {
   24     mem[i] = 'A' + i;
   25     sleep(1);
   26     i++;
   27     mem[i] = 0;
   28   }
   29 
   30   shmdt(mem);
   31 
   32   return 0;
   33 }

可以看到我们实现了client端向server端通过共享内存进行信息的传输

共享内存的特点

1、共享内存是所有进程通信中速度最快的,因为它没有使用OS接口,拷贝次数减少

2、不提供任何保护机制(同步与互斥)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/350176.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Modern C++ std::bind的实现原理-举例

上节《Modern C std::bind的实现原理-CSDN博客》主要讲的是原理&#xff0c;本节举个例子并画图帮助理解。 上程序&#xff1a; #include <functional> #include <iostream>// A function taking three arguments void printValues(int a, double b, const std::…

探秘Dmail:Web3世界的通讯引领者

摘要&#xff1a;在一个充满潜力并且对创新要求严格的领域中&#xff0c;Dmail作为一种开创性的Web3通讯协议应运而生。 1月24日&#xff0c;OKX Jumpstart宣布上线Dmail&#xff0c;在Web3领域引起了巨大反响&#xff0c;这是一个旨在重新定义数字通讯范式的富有远见的项目&a…

【快影】怎么去除视频上不想要的东西?

您好&#xff0c;您可以试试编辑器中的「一键修复」功能&#xff0c;选中主轨或者画中画&#xff0c;点击底部一键修复功能&#xff0c;框选视频中不想要的内容&#xff0c;点击生成&#xff0c;即可预览修复效果&#xff1b;目前该功能是VIP专属功能&#xff0c;开通快影VIP即…

web前端项目-动画特效【附源码】

文章目录 一&#xff1a;赛车游戏动画HTML源码&#xff1a;JS源码&#xff1a;CSS源码&#xff1a;&#xff08;1&#xff09;normalize.css&#xff08;2&#xff09;style.css 二&#xff1a;吉普车动画演示HTML源码&#xff1a;CSS源码&#xff1a;&#xff08;1&#xff09…

Docker 容器内运行 mysqldump 命令来导出 MySQL 数据库,自动化备份

备份容器数据库命令&#xff1a; docker exec 容器名称或ID mysqldump -u用户名 -p密码 数据库名称 > 导出文件.sql请替换以下占位符&#xff1a; 容器名称或ID&#xff1a;您的 MySQL 容器的名称或ID。用户名&#xff1a;您的 MySQL 用户名。密码&#xff1a;您的 MySQL …

【自动化测试】测试开发工具大合集

收集和整理各种测试工具&#xff0c;自动化测试工具&#xff0c;自动化测试框架&#xff0c;觉得有帮助记得三连一下。 欢迎提交各类测试工具到本博客。 通用测试框架 JUnit: 最著名的xUnit类的单元测试框架&#xff0c;但是不仅仅可以做单元测试。TestNG: 更强大的Java测试框…

CSS 实现 flex布局最后一行左对齐的方案「多场景、多方案」

目录 前言解决方案场景一、子项宽度固定&#xff0c;每一行列数固定方法一&#xff1a;模拟两端对齐方法二&#xff1a;根据元素个数最后一个元素动态margin 场景二、子项的宽度不确定方法一&#xff1a;直接设置最后一项 margin-right:auto方法二&#xff1a;使用:after(伪元素…

遇到这3种接口测试问题,其实,你可以这么办~

作为整个软件项目的必经环节&#xff0c;软件测试是不可缺少的“查漏补缺”环节。而作为软件测试中的重要一环——接口测试&#xff0c;几乎串联了整个项目所有的输入和输出环节。 前几年&#xff0c;我在做后端测试时&#xff0c;接触最多的正是接口测试。基于此&#xff0c;…

python使用PaddleOCR实现《命名实体识别项目》OCR(已实现)(ai领域必看,简单易用)

1.简介&#xff1a; PaddleOCR是飞桨&#xff08;PaddlePaddle&#xff09;推出的一个端到端的光学字符识别开源工具集&#xff0c;支持中文、英文、数字以及特殊符号等各种类型的文字检测、识别和词语整体识别。该工具集使用PaddlePaddle深度学习框架技术&#xff0c;提供了多…

【斯坦福计网CS144项目】Lab2 实现一个简单的 TCP 接收类

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

21.Arrays类

Arrays类 1. 概述2. 常见方法3. sort 方法的自定义排序4. 代码示例5. 输出结果6. 注意事项 1. 概述 Arrays类是Java中的一个工具类&#xff0c;位于java.util包中。 它提供了一组静态方法&#xff0c;用于操作数组。通过Arrays类&#xff0c;我们可以对数组进行复制、填充、排…

【第四天】蓝桥杯备战

题 1、求和2、天数3、最大缝隙 1、求和 https://www.lanqiao.cn/problems/1442/learning/ 解法&#xff1a;字符串方法的应用 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scann…

MSG3D论文解读

论文在stgcn与sta-lstm基础上做的。下面讲一下里面的方法&#xff1a; 1.准备工作 符号。这里是对符号进行解释。 一个人体骨骼图被记为G(v,E) 图卷积&#xff1a; 图卷积定义 考虑一种常用于处理图像的标准卷积神经网络 (CNN)。输入是像素网格。每个像素都有一个数据值向…

kubeSphere DevOps自定义容器 指定nodejs版本

✨✨✨✨✨✨ &#x1f380;前言&#x1f381;基于内置镜像构建&#x1f381;把镜像添加基础容器中&#x1f381;检查容器是否配置成功&#x1f381;不生效的原因排查&#x1f381;按步骤执行如下命令 &#x1f380;前言 由于我本地的开发环境node是16.18.1,而自带容器node的版…

项目中遇到通过域名访问服务提示 Service name unknow

目录 项目中遇到通过域名访问服务提示 Service name unknow 1.问题描述2.问题原因3.解决思路4.解决方案文章所属专区 项目问题解决 1.问题描述 在CentOS 系统环境下 项目中遇到通过域名访问服务提示 Service name unknow,但是 网络是连通的 通过ping 和telnet都能够验证。 …

win10+elasticsearch8.12 安装教程

Elasticsearch是一种搜索引擎&#xff0c;本地安装完成之后&#xff0c;可使用其他编程语言&#xff08;例如python&#xff09;与elasticsearch建立连接&#xff0c;然后使用python脚本搜索elasticsearch中的数据 1下载 elasticsearch elasticsearch最新版官网下载链接 点击…

Pandas.DataFrame.product() 乘积(累乘积) 详解 含代码 含测试数据集 随Pandas版本持续更新

关于Pandas版本&#xff1a; 本文基于 pandas2.2.0 编写。 关于本文内容更新&#xff1a; 随着pandas的stable版本更迭&#xff0c;本文持续更新&#xff0c;不断完善补充。 传送门&#xff1a; Pandas API参考目录 传送门&#xff1a; Pandas 版本更新及新特性 传送门&…

让B端管理软件既美观又实用的解决方案来了

hello宝子们...我们是艾斯视觉擅长ui设计和前端开发10年经验&#xff01;希望我的分享能帮助到您&#xff01;如需帮助可以评论关注私信我们一起探讨&#xff01;致敬感谢感恩&#xff01; 让B端管理软件既美观又实用的解决方案来了 在当今数字化时代&#xff0c;B端管理软件已…

Docker容器部署OpenCV,打造高效可移植的计算机视觉开发环境

推荐 海鲸AI-ChatGPT4.0国内站点&#xff1a;https://www.atalk-ai.com 前言 在计算机视觉领域&#xff0c;快速部署和测试算法是研究和开发的关键。OpenCV作为一个强大的开源计算机视觉库&#xff0c;广泛应用于各种图像处理和视频分析任务。然而&#xff0c;配置OpenCV环境可…

计算机毕业设计 | SpringBoot 求职招聘管理系统(附源码)

1&#xff0c;绪论 1.1 开发背景 高学历人群是网络求职者的主体&#xff0c;且结构趋向固定。而在疫情肆虐的今日&#xff0c;线上招聘成了越来越多企业和个人选择的方式。在疫情期间线下招聘转为线上招聘&#xff0c;是疫情防控的需要。不能否定的是新的招聘模式的出现一定会…