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 0x666610 #define SIZE 409611 12 #endif                                                                                                                                                                                                       
    //sever.c1 #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.h1 #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 0x666610 #define SIZE 409611 12 #endif        
//server.c1 #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.c1 #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、不提供任何保护机制(同步与互斥)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小电影网站上线之nginx配置不带www域名301重定向到www域名+接入腾讯云安全防护edgeone

背景 写了个电影网站&#xff08;纯粹搞着玩的&#xff09;&#xff0c;准备买个域名然后上线&#xff0c;但是看日志经常被一些恶意IP进行攻击&#xff0c;这里准备接入腾讯云的安全以及加速产品edgeone&#xff0c;记录下当时的步骤。 一、nginx配置重定向以及日志格式 ng…

webpack常用配置

1.webpack概念 ​ 本质上&#xff0c;webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时&#xff0c;它会在内部从一个或多个入口点构建一个 依赖图(dependency graph)&#xff0c;然后将你项目中所需的每一个模块组合成一个或多个 …

IDEA远程服务器开发

IDEA的远程开发是在本地去操远程服务器上的代码&#xff0c;可以直接将本地代码的编译,构建,调试,运行等工作都放在远程服务器上而本地运行一个客户端远程去操作服务器上的代码,就如同我们平常写代码一样。相比于云桌面成本更低,开发效率更高。 1.首先服务器配置jdk&#xff0…

win10通过ssh链接deepin23并开启x11转发

前提 主机环境&#xff1a;win10 lstc 虚拟机环境&#xff1a;deepin23beta2 终端&#xff1a;tabby x11服务器: vcxsrv 安装ssh sudo apt install ssh开启root登录(看你需求&#xff09; 首先你要给root账号设置密码 sudo passwd root修改配置文件 sudo vim /etc/ssh/ss…

gitee仓库使用中的警告

当 Git 执行 git pull 命令时&#xff0c;有时候会出现类似下面的警告信息&#xff1a; warning: ----------------- SECURITY WARNING ---------------- warning: | TLS certificate verification has been disabled! | warning: ------------------------------------------…

ASP.NET Core WebAPI从HTTPS调整为HTTP启动

使用VS2022创建WebAPI项目时&#xff0c;默认勾选“配置HTTPS(H)”&#xff0c;这样启动WebAPI时以https方式启动。   如果要从HTTPS调整为HTTP启动&#xff0c;需要修改项目中以下几处&#xff0c;首先是Program.cs中删除app.UseHttpsRedirection()语句&#xff0c;删除后…

数据结构与算法:复杂度

友友们大家好啊&#xff0c;今天开始正式学习数据结构与算法有关内容&#xff0c;后续不断更新数据结构有关知识内容&#xff0c;希望多多支持&#xff01; 数据结构&#xff1a; 数据结构是用于存储和组织数据的方式&#xff0c;以便可以有效地访问和修改数据。不同的数据结构…

E5071C 是德科技网络分析仪

181/2461/8938产品概述&#xff1a; E5071C ENA 矢量网络分析仪&#xff0c;9 kHz 至 20 GHz&#xff0c;配有增强型 TDR 测量选件。 E5071C 是大规模无源元器件测试的理想解决方案。 它具有出色的测量性能&#xff0c;有助于提高测试吞吐量&#xff0c;尤其是与 E5092A 多端…

REVIT二次开发万能刷

将这两个参数赋予其他参数 步骤2 将来做个可以调控的版本 using System; using System.Collections.Generic; using System.Lin

C动态内存那些事

为什么存在动态内存分配&#xff1f; 首先&#xff0c;动态内存分配是计算机中一种重要的内存管理方法&#xff0c;它主要解决了静态内存分配无法灵活应对变化需求的问题。以下是几个存在动态内存分配的原因&#xff1a; 灵活性&#xff1a;动态内存分配允许程序在运行时根据需…

Allure 内置特性

章节目录&#xff1a; 一、内置特性概述二、展示环境信息三、测试结果分类四、用例步骤说明五、添加附件六、添加用例描述七、设置动态的用例标题八、报告中添加链接九、组织测试结果9.1 使用与理解9.2 指定运行 十、划分用例级别十一、动态生成附加信息十二、清空历史报告记录…

【GitHub项目推荐--如何构建项目】【转载】

这是一个 138K Star 的开源项目&#xff0c;这个仓库汇集了诸多优质资源&#xff0c;教你如何构建一些属于自己的东西&#xff0c;内容主要分为增强现实、区块链、机器人、编辑器、命令行工具、神经网络、操作系统等几大类别。 开源地址&#xff1a;https://github.com/danist…

vue 样式隔离原理

日常写单文件组件时&#xff0c;会在style添加scoped属性&#xff0c;如<style scoped>&#xff0c;目的是为了隔离组件与组件之间的样式&#xff0c;如下面的例子&#xff1a; <template><p class"foo">这是foo</p><p class"bar&q…

ubuntu下docker卸载和重新安装

卸载&#xff1a;步骤一&#xff1a;停止Docker服务 首先&#xff0c;我们需要停止正在运行的Docker服务。打开终端&#xff0c;执行以下命令&#xff1a; sudo systemctl stop docker 步骤二&#xff1a;删除Docker安装包 接下来&#xff0c;我们需要删除已经安装的Docker软件…

微信小程序如何自定义单选和多选

实现单选 实现效果:点击显示单选状态,每次仅能点击一个元素。 实现方式: wxml: <view wx:for="{{item_list}}" data-info="{{index}}" class="{{menu_index===index?choose:no_choose}}" bind:tap="changeColor">{{ite…

25考研每日的时间安排

今天要给大家分享一下25考研每日的时间安排。 没有完美的计划&#xff0c;只有合适的计划。 仅供参考 很多人说复习不要只看时长而是要看效率&#xff0c;所以学多长时间不重要&#xff0c;重要的高效率完成任务。 完美的计划 这个计划看起来很完美&#xff0c;从早到晚有学习…

尚无忧球馆助教系统源码,助教小程序源码,助教源码,陪练系统源码

特色功能&#xff1a; 不同助教服务类型选择 助教申请&#xff0c;接单&#xff0c;陪练师入住&#xff0c;赚取外快 线下场馆入住 设置自己服务 城市代理 分销商入住 优惠券 技术栈&#xff1a;前端uniapp后端thinkphp 独立全开源

【C++基础】析构函数和构造函数面试知识点总结

&#x1f308;欢迎来到C基础专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mysq…

大脑的漏洞:你是如何走向狭隘和顽固的?

在这篇文章的最开始&#xff0c;我想请大家思考一个问题&#xff1a; 为什么谣言的传播总是非常容易&#xff0c;但辟谣却一点也不容易呢&#xff1f; 有一个非常简单的答案&#xff0c;你或许立刻就能想到&#xff1a;因为谣言一般都非常简单&#xff0c;但辟谣一般都不怎么简…

linux安装docker--更具官网教程

1.访问https://docs.docker.com/ 2.进入download 3输入cento 或者直接访问地址Install Docker Engine on CentOS | Docker Docs 4一步一步根据官网命令走 2安装 3 4 方式一&#xff1a; service docker start&#xff08;开启&#xff09; service docker status&#xff08…