Linux:System V - 共享内存

1.System V共享内存的原理

通过为用户提供系统调用接口,让用户可以申请一块空间,进程A/B也可以通过系统调用接口将创建好的内存通过页表映射进进程的地址空间。完成让不同的两个进程看见同一份资源的目的。如果未来不想继续通信,取消进程和内存的映射关系,释放内存。这块在物理内存上申请的这段空间称为共享内存,让进程和共享内存关联起来的行为叫做挂接,取消进程和内存的映射关系叫做去关联。
这种申请共享内存的方式不能使用Malloc,malloc也可以在物理内存上申请空间,返回它的虚拟地址;但是malloc没有提供让其它进程也看到这块内存的接口,只是本进程私有。

2.共享内存的概念

通过让不同的进程看到同一个内存块的方式就叫做共享内存。

IPC_CREAT:不存在就创建,存在即获取它。
IPC_EXCL:无法单独使用。和IPC_CREAT组合使用:不存在就创建,存在就出错返回,如果创建成功,一定是一个新的shm!

如果两个进程传入的pathname是一样的,那么key值就一样,就能唯一性看到同一个共享内存。


再谈key:
在操作系统存在多个共享内存;key值是多少没表示什么含义,能进行唯一性标识最重要。
C语言中free(p)?->语言库对申请出来的空间做管理,会多余申请空间。共享内存也是如此,先描述,再组织;共享内存=物理内存块+共享内存相关属性。只要另一个进程拿到同一个key就可以访问到需要通信的共享内存;key作为共享内存结构的一个属性struct shm,在创建共享内存时就传参设置key值,获取共享内存时就是查找key值匹配的struct shm。
shmid:
shmid->fd;key->inode;内核级的标定和上层的标定;shmid和fd都是给用户使用的用来标识的。为什么不统一使用key和inode?用于在不同场景下的解耦,防止系统改变影响应用层。

1.如何查看IPC资源

管道:通信进程退出了,文件描述符自动被释放;共享内存在进程退出后,依旧存在(用ipcs -m查看共享内存;ipcs -q消息队列;ipcs -s信号量;ipcrm -m shmid删除某个共享内存)
2.IPC资源的特征:
共享内存的生命周期是随操作系统的,不随进程;System V版本通信的共性。


让共享内存和进程关联起来

通过修改页表,创建的共享内存和当前进程关联起来,在虚拟地址空间中找到一个没有被使用的空间,建立映射关系之后把它的起始地址返回,返回值就是共享内存空间在虚拟内存的起始地址。


在用完后可以直接把共享内存删掉,但是先去关联再删除会比较完善

共享内存的特点:
优点:所有进程通信中速度最快的!只要进程1将内容写入,进程2立马就能看到,减少数据拷贝次数(不用定义buffer)。同样的代码,键盘输入和显示器输出,用管道和共享内存来实现分别需要多少次拷贝?4/2
缺点:当发的速度慢,读的快时,会一直打印陈旧数据;共享内存不进行同步和互斥的操作的,没有对数据做任何保护。改善:没通知server时,令其阻塞等待,通过再建立一个匿名管道,每当client端写入共享内存信息时,给管道也传入一个信号;当server端读取时先阻塞等待管道信号。

comm.hpp :为shm_server和shm_client提供了7个接口

#ifndef _COMM_HPP_
#define _COMM_HPP_
#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <cstdio>
#define PATHNAME "."
#define PROJ_ID 0x66
#define MAX_SIZE 4096
//系统分配共享内存是以4KB为单位的,向上取整;尽量按照4kb的整数倍;一个4KB相当于一个Page
key_t getKey()
{key_t k = ftok(PATHNAME,PROJ_ID);//可以获取同样的keyif(k<0){//cin,cout,cerr -> stdin,stdout,stderr -> 0 1 2;//cerr向标准错误中打印,strerror(errno)把错误码转换成错误描述std::cerr<<errno<<":"<<strerror(errno)<<std::endl;exit(1);//终止程序}return k;
}
int getShmHelper(key_t k,int flags)
{int shmid = shmget(k,MAX_SIZE,flags);if(shmid<0)//获取失败{std::cerr<<errno<<":"<<strerror(errno)<<std::endl;exit(2);//终止程序}return shmid;
}
int getShm(key_t k)//给之后的进程使用,获取共享内存
{//存在就获取,不存在创建return getShmHelper(k,IPC_CREAT/*0*/);//也可以设置0,0的语义和IPC_CREAT相同。
}
int createShm(key_t k)//给第一个进程使用,创建共享内存
{return getShmHelper(k,IPC_CREAT|IPC_EXCL|0600);//获取失败返回错误
}
void *attachShm(int shmid)//把共享内存贴到虚拟地址空间上
{void *mem = shmat(shmid,nullptr,0);//挂接if((long long)mem == -1L){std::cerr<<errno<<":"<<strerror(errno)<<std::endl;exit(3);}return mem;
}
void detachShm(void *start)
{if(shmdt(start)==-1){std::cerr<<errno<<":"<<strerror(errno)<<std::endl;}
}
void delShm(int shmid)
{if(shmctl(shmid,IPC_RMID,nullptr)==-1){std::cerr<<errno<<":"<<strerror(errno)<<std::endl;}
}
#endif

shm_server.cc:

#include "comm.hpp"
int main()
{//获取唯一标识keykey_t k = getKey();printf("key:0x%x\n",k);//key//创建共享内存int shmid = createShm(k);printf("shmid:%d\n",shmid);//shmidsleep(5);//将共享内存和进程关联起来char *start = (cahr*)attachShm(shmid);printf("attach success,address start:%p\n",start);while(true){//char buffer[];read(pipefd,buffer,...)printf("client say: %s\n",start);sleep(1);}//在用完后可以直接把共享内存删掉,但是先去关联再删除会比较完善detachShm(start);sleep(5);//释放共享内存delShm(shmid);return 0;
}

shm_client.cc: 

#include "comm.hpp"
#include <unistd.h>
int main()
{key_t k = getKey();printf("key:0x%x\n",k);//获取共享内存int shmid = getShm(k);printf("shmid:%d\n",shmid);sleep(5);//共享内存和进程关联char *start = (char*)sttachShm(shmid);printf("attach success,address start:%p\n",start);const char* message = "hello server,我是另一个进程,正在和你通信";pid_t id = getpid();int cnt = 1;//char buffer[1024];while(true){snprintf(start,MAX_SIZE,"%s[pid:%d][消息编号:%d]",message,id,cnt);// snprintf(buffer,sizeof(buffer),"%s[pid:%d][消息编号:%d]",message,id,cnt);//将特定的字段格式化,写入字符串中// memcpy(start,buffer,strlen(buffer)+1);//pid,count,message}//在用完后可以直接把共享内存删掉,但是先去关联再删除会比较完善detachShm(start);return 0;
}

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

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

相关文章

SpringBoot错误码国际化

先看测试效果&#xff1a; 1. 设置中文 2.设置英文 文件结构 1.中文和英文的错误消息配置 package com.ldj.mybatisflex.common;import lombok.Getter;/*** User: ldj* Date: 2025/1/12* Time: 17:50* Description: 异常消息枚举*/ Getter public enum ExceptionEnum {//…

道旅科技借助云消息队列 Kafka 版加速旅游大数据创新发展

作者&#xff1a;寒空、横槊、娜米、公仪 道旅科技&#xff1a;科技驱动&#xff0c;引领全球旅游分销服务 道旅科技 &#xff08;https://www.didatravel.com/home&#xff09; 成立于 2012 年&#xff0c;总部位于中国深圳&#xff0c;是一家以科技驱动的全球酒店资源批发商…

Solidity01 Solidity极简入门

一、Solidity 简介 Solidity 是一种用于编写以太坊虚拟机&#xff08;EVM&#xff09;智能合约的编程语言。我认为掌握 Solidity 是参与链上项目的必备技能&#xff1a;区块链项目大部分是开源的&#xff0c;如果你能读懂代码&#xff0c;就可以规避很多亏钱项目。 Solidity …

如何使用WPS的JS宏实现Word表格的自动编号

如何使用WPS的JS宏实现Word表格的自动编号&#xff1f;如下图&#xff0c;想要给表格的编号列中添加序号。 使用WPS的JS宏可以实现自动编号&#xff0c;代码如下&#xff1a; n Selection.Tables.Item(1).Rows.Count;for(i 2;i<n;i){Selection.Tables.Item(1).Cell(i,1).…

Python在多个Excel文件中找出缺失数据行数多的文件

本文介绍基于Python语言&#xff0c;针对一个文件夹下大量的Excel表格文件&#xff0c;基于其中每一个文件内、某一列数据的特征&#xff0c;对其加以筛选&#xff0c;并将符合要求与不符合要求的文件分别复制到另外两个新的文件夹中的方法。 首先&#xff0c;我们来明确一下本…

【Linux】应用层自定义协议与序列化

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 应用层 &#x1f98b; 再谈 "协议"&#x1f98b; 网络版计算器&#x1f98b; 序列化 和 反序列化 二&#xff1a;&#x1f525; 重新理解 read、…

数字化贷款管理:助贷系统软件为贷款中介带来的五大改变

随着金融行业的数字化转型&#xff0c;贷款中介的业务模式也在不断创新。助贷系统作为数字化管理的核心工具&#xff0c;正在为贷款中介带来深刻的变革。本文将从五个方面探讨助贷系统软件如何改变贷款中介行业的管理模式&#xff0c;提升业务效率&#xff0c;降低运营成本。乐…

MIAOYUN信创云原生项目亮相西部“中试”生态对接活动

近日&#xff0c;以“构建‘中试’生态&#xff0c;赋能科技成果转化”为主题的“科创天府智汇蓉城”西部“中试”生态对接活动在成都高新区菁蓉汇隆重开幕。活动分为成果展览、“中试”生态主场以及成果路演洽谈对接三大板块。在成果展览环节&#xff0c;成都元来云志科技有限…

一文简要了解为什么需要RAG、核心原理与应用场景

欢迎来到AI应用探索&#xff0c;这里专注于探索AI应用。 一、为什么需要RAG&#xff0c;它解决了哪些问题 在自然语言处理领域&#xff0c;生成式预训练模型&#xff08;如GPT&#xff09;已经展示了强大的文本生成能力。然而&#xff0c;这些模型有以下局限性&#xff1a; 知…

gametime

gametime 一、查壳 无壳&#xff0c;32位 二、IDA分析 先看看main 妈呀&#xff0c;好多函数&#xff0c;脑子有点乱 先运行下EXE看看有什么突破口没 可以看出是游戏&#xff0c;明显是看你的输入对不对&#xff0c;来通关的&#xff0c;所以有关判定的条件或者函数是解题…

基于机器学习随机森林算法的个人职业预测研究

1.背景调研 随着信息技术的飞速发展&#xff0c;特别是大数据和云计算技术的广泛应用&#xff0c;各行各业都积累了大量的数据。这些数据中蕴含着丰富的信息和模式&#xff0c;为利用机器学习进行职业预测提供了可能。机器学习算法的不断进步&#xff0c;如深度学习、强化学习等…

【Linux】Socket编程-TCP构建自己的C++服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; Socket 编程 TCP &#x1f98b; TCP socket API 详解&#x1f98b; 多线程远程命令执行&#x1f98b; 网络版计算器&#xff08;应用层自定义协议与序列化…

C++(二十一)

前言&#xff1a; 本文承接上文&#xff0c;将详细讲解指针概念。 一&#xff0c;通过指针了解变量的数值。 在将变量地址存入指针后&#xff0c;从指针反推也可以知道原变量的值&#xff0c;若想进行反退&#xff0c;就需要使用间接引用运算符&#xff1a;*。 语法&#x…

Windows图形界面(GUI)-QT-C/C++ - Qt List Widget详解与应用

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 QListWidget概述 使用场景 常见样式 QListWidget属性设置 显示方式 (Display) 交互行为 (Interaction) 高级功能 (Advanced) QListWidget常见操作 内容处理 增加项目 删除项目…

一文了解如何使用 DBeaver 管理 DolphinDB

在日常的数据开发、分析和数据库运维中&#xff0c;一款优秀的 IDE 能够极大地提升工作效率。DBEaver 是一款由 Java 编写的一站式跨平台连接器&#xff0c;其社区版本已能支持连接近百种数据库&#xff0c;受到广大开发者的喜爱。近期。DolphinDB 与 DBeaver 团队共同努力&…

CSRF攻击XSS攻击

概述 ​在 HTML 中&#xff0c;<a>, <form>, <img>, <script>, <iframe>, <link> 等标签以及 Ajax 都可以指向一个资源地址&#xff0c;而所谓的跨域请求就是指&#xff1a;当前发起请求的域与该请求指向的资源所在的域不一样。这里的域指…

【机器学习实战入门】使用 Pandas 和 OpenCV 进行颜色检测

Python 颜色检测项目 今天的项目将非常有趣和令人兴奋。我们将与颜色打交道&#xff0c;并在项目过程中学习许多概念。颜色检测对于识别物体来说是必要的&#xff0c;它也被用作各种图像编辑和绘图应用的工具。 什么是颜色检测&#xff1f; 颜色检测是检测任何颜色名称的过程…

vue2 web 多标签输入框 elinput是否当前焦点

又来分享一点点工作积累及解决方案 产品中需要用户输入一些文字后按下回车键生成标签来显示在页面上&#xff0c;经过尝试与改造完成如下&#xff1a; <template><div class"tags-view" click"beginInput"><el-tag :key"index" …

SSE 实践:用 Vue 和 Spring Boot 实现实时数据传输

前言 大家好&#xff0c;我是雪荷。最近我在灵犀 BI 项目中引入了 SSE 技术&#xff0c;以保证图表的实时渲染&#xff0c;当图表渲染完毕服务端推送消息至浏览器端触发重新渲染。 什么是 SSE&#xff1f; SSE 全称为 Server-Send Events 意思是服务端推送事件。 SSE 相比于 …

记录一次 centos 启动失败

文章目录 现场1分析1现场2分析2搜索实际解决过程 现场1 一次断电,导致 之前能正常启动的centos 7.7 起不来了有部分log , 关键信息如下 [1.332724] XFS(sda3): Internal error xfs ... at line xxx of fs/xfs/xfs_trans.c [1.332724] XFS(sda3): Corruption of in-memory data…