进程间通信——共享内存

       

目录

共享内存的原理

共享内存通信的实现步骤

通信实例


共享内存的原理

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

总结:共享内存的通信原理就是让不同的进程看到同一份内存。 

共享内存通信的实现步骤:

1、创建key,通过调用ftok()生成标识共享内存的key值。

2、创建共享内存,使用shmget()向OS申请一段内存。

3、将共享内存和要进行通信的进程关联。

4、进行数据通信和通信数据的处理。

5、通信完成后,将所有进程和共享内存去关联。

6、删除共享内存。

注意:共享内存的创建只需一个进程进行即可,其余要进行通信的进程,则需要获取共享内存。

共享内存的创建

调用shmget( )创建共享内存

函数原型:

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

功能:用来创建共享内存。

参数

key:这个共享内存段名字。

size:共享内存大小。

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

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

关于shmget( )的第一个参数key,是用于标识共享内存的唯一性,通过调用ftok( )使用一定的算法生成的。

ftok()原型:

key_t ftok(const char *pathname, int proj_id);

参数说明:

pathname:一个已存在的路径。

proj_id:项目id。 

函数功能:将一个已存在的路径和项目id转换为一个key值。

shmget( )的第三个参数shmflg创建共享内存的方式,常见的是用方式:

单独使用IPC_CREAT: 创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,获取已经存在的共享内存并返回。IPC_EXCL不能单独使用,一般都要配合IPC_CREAT。

IPC_CREAT | IPC_EXCL: 创建一个共享内存,如果共享内存不存在,就创建之, 如果已经存在,则立马出错返回 -- 如果创建成功,对应的shm,一定是最新的!

这里我们先记住在多个进程要使用同一个共享内存时仅需一个进程使用IPC_CREAT | IPC_EXCL组合,其余进程单独使用IPC_CREAT。

进程和共享内存关联

shmat()

原型

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

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

参数

shmid: 共享内存标识。

shmaddr:指定连接的地址。

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

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

说明:

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

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

shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。

公式:shmaddr - (shmaddr % SHMLBA) shmflg=SHM_RDONLY,表示连接操作用来只读共享内存。

进程和共享内存去关联

shmdt()

函数原型:

int shmdt(const void *shmaddr);

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

参数 shmaddr: 由shmat所返回的指针。

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

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

shmctl( )

原型

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

功能:用于控制共享内存.

参数

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

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

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

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

通信实例:

server.cc

#include"comm.hpp"
#include<unistd.h>int main(){//1、创建key
key_t k =getKey();
cout<<"server key:"<<toHex(k)<<endl;//2、创建共享内存
int shmid=createShm(k,gsize);
cout<<"server shmid: "<<shmid<<endl;
sleep(3);//3、将当前进程和共享内存内存关联
char* start=attachShm(shmid);
//sleep(20);//4、进行通信
//char* start=attachShm(shmid);//init.getStart();
int n=0;
while(n<=30)
{cout<<"client -> server# "<<start<<endl;sleep(1);n++;
}//5、通信完成 将当前进程和共享内存去关联
detachShm(start);//删除共享内存delShm(shmid);return 0;}

client.cc

#include"comm.hpp"
#include<unistd.h>
int main()
{//1、获取共享内存
key_t k=getKey();
cout<<"client key: "<<toHex(k)<<endl;int shmid=getShm(k,gsize);
cout<<"client shmid: "<<shmid<<endl;//2、将当前进程和共享内存关联
char* start=attachShm(shmid);
//3、进行通信
//char* start=(char*)attachShm(shmid);//init.getStart();
char c='A';
while(c<='Z')
{start[c-'A']=c;c++;start[c-'A']='\0';sleep(1);
}
//sleep(15);//4、将当前进程和共享内存去关联
detachShm(start);
return 0;}

comm.hpp

#ifndef __COMM_HPP__
#define __COMM_HPP__#include<iostream>
#include<cerrno>
#include<cstdio>
#include<cstring>
#include<cassert>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<sys/stat.h>using namespace std;
#define PATHNAME "."
#define PROJID 0X6666const int gsize =4096;key_t getKey()
{key_t k =ftok(PATHNAME,0X6666);if(k==-1){cerr<<"error: "<<errno<<" : "<<strerror(errno)<<endl;exit(1);}return k;
}
string toHex(int x)
{char buffer[64];snprintf(buffer,sizeof buffer,"0x%x",x);return buffer;
}static int createShmHelper(key_t k,int gsize,int flog)
{int shmid=shmget(k,gsize,flog);if(shmid==-1){cerr<<"cerror: "<<errno<<" : "<<strerror(errno)<<endl;exit(2);}return shmid;
}int createShm(key_t k,int size)
{umask(0);return createShmHelper(k,size,IPC_CREAT|IPC_EXCL|0666);
}int getShm(key_t k,int size)
{return createShmHelper(k,size,IPC_CREAT);
}char* attachShm(int shmid)
{char*start=(char*)shmat(shmid,nullptr,0);return start;
}
void detachShm(char*start)
{int n=shmdt(start);assert(n!=-1);(void)n;
}void delShm(int shmid)
{int n=shmctl(shmid,IPC_RMID,nullptr);assert(n!=-1);(void)n;
}#endif

运行结果:

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

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

相关文章

C语言 —— 初步入门知识(第一个C语言程序、数据类型、变量常量、字符与注释)

本篇文章介绍C语言的基础知识&#xff0c;使读者对C语言能够有一个大概的认识. 不会细写每一个知识点, 但是能够入门C语言, 进行初步的C语言代码阅读. 首先, 什么是语言? 对于人和人之间进行交流的语言, 我们知道, 可以通过汉语, 英语, 日语等语言进行交流. 那么对于人和计算…

计算机网络:三次握手与四次挥手

摘取作者&#xff1a;拓跋阿秀 三次握手 三次握手&#xff08;Three-way Handshake&#xff09;其实就是指建立一个TCP连接时&#xff0c;需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后…

SpringMVC系列(四)之SpringMVC实现文件上传和下载

目录 前言 一. SpringMVC文件上传 1. 配置多功能视图解析器 2. 前端代码中&#xff0c;将表单标记为多功能表单 3. 后端利用MultipartFile 接口&#xff0c;接收前端传递到后台的文件 4. 文件上传示例 1. 相关依赖&#xff1a; 2. 逆向生成对应的类 3. 后端代码&#xf…

(10)(10.9) 术语表(一)

文章目录 前言 1 2.4Ghz 2 AGL 3 AHRS 4 APM 5 AMA 6 Arduino 7 APM (AutoPilot Mega) 8 ATC 9 Copter 10 Plane 11 Rover 12 BEC 13 Bootloader 14 COA 15 DCM 16 Eagle file 17 ESC 18 Firmware 19 FPV 20 FTDI 前言 &#xff01;Note 术语表未编入索…

微信小程序学习笔记1.0

第1章 微信小程序基础 1.1 微信小程序介绍 1.1.1 什么是微信小程序 微信小程序的特点&#xff1a; ① 微信小程序是不需要下载和安装的&#xff1b; ② 它可以完成App应用软件的交互功能&#xff1b; ③ 用户扫一扫或者搜一下就可以使用小程序&#xff1b; ④ 微信小程序…

Python模板注入(SSTI)

概念 发生在使用模板引擎解析用户提供的输入时。模板注入漏洞可能导致攻击者能够执行恶意代码或访问未授权的数据。 模板引擎可以让&#xff08;网站&#xff09;程序实现界面与数据分离&#xff0c;业务代码与逻辑代码分离。即也拓宽了攻击面&#xff0c;注入到模板中的代码可…

数据库逻辑透明-架构真题(二十九)

&#xff08;2020年&#xff09;假设某计算机字长为32位&#xff0c;该计算机文件管理系统磁盘空间管理采用位示图&#xff08;bitmap&#xff09;记录磁盘的使用情况。若磁盘的容量为300GB&#xff0c;物理块大小为4MB&#xff0c;那么位示图的大小为&#xff08;&#xff09;…

海外媒体发稿:海外汽车媒体推广9个方式解析

根据下列9个国外汽车媒体推广方式&#xff0c;企业能够在国际范围内突破边界&#xff0c;获得领域关心。这将帮助企业完成国际化发展发展战略&#xff0c;扩展市场占有率和提升盈利空间。【华媒舍】国外全媒体发表文章将会成为企业完成这一目标的重要方式&#xff0c;为企业带来…

Java中的异常基础知识

目录 什么是异常? 1.算术异常 2.数组越界异常 3.空指针异常 4.输入不匹配异常 Java异常体系 异常的处理 防御式编程: 事后认错 异常处理流程 自定义异常 什么是异常? 在Java中,将程序执行过程中发生的不正常行为称为异常 1.算术异常 public static void main(St…

GDB之保存已经设置的断点(十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

postgresql-窗口函数种类

postgresql-聚合窗口函数 聚合函数排名窗口函数案例1案例2 取值窗口函数环比增长率同比增长率 聚合函数 常用的聚合函数&#xff0c;例如 AVG、SUM、COUNT 等&#xff0c;也可以作为窗口函数使用 --计算移动平均值 select saledate, amount, avg(amount) over (order by sale…

【用unity实现100个游戏之10】复刻经典俄罗斯方块游戏

文章目录 前言开始项目网格生成Block方块脚本俄罗斯方块基类&#xff0c;绘制方块形状移动逻辑限制移动自由下落下落后设置对应风格为不可移动类型检查当前方块是否可以向指定方向移动旋转逻辑消除逻辑游戏结束逻辑怪物生成源码参考完结 前言 当今游戏产业中&#xff0c;经典游…

U8用友ERP本地部署异地远程访问:内网端口映射外网方案

文章目录 前言1. 服务器本机安装U8并调试设置2. 用友U8借助cpolar实现企业远程办公2.1 在被控端电脑上&#xff0c;点击开始菜单栏&#xff0c;打开设置——系统2.2 找到远程桌面2.3 启用远程桌面 3. 安装cpolar内网穿透3.1 注册cpolar账号3.2 下载cpolar客户端 4. 获取远程桌面…

python使用钉钉机器人给钉钉发送消息

import requestsdef dingmessage(msg):urlhttps://oapi.dingtalk.com/robot/send?access_token2c5e2b764129e936ba9c43713a588caa7eeb168c132223a91ba97d80a6fee337data{msgtype:text,text:{content: 通知:msg}}resrequests.post(url,jsondata)

界面组件DevExpress WinForms v23.1 - 增强的图表、甘特图功能

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

冠达管理:Arm上市首日大涨25%,成为年度美股规模最大IPO

9月15日清晨&#xff0c;软银旗下芯片规划公司ARM在纳斯达克交易所首日上市&#xff0c;收盘大涨近25%&#xff0c;市值达到679亿美元&#xff0c;成为本年度美股规模最大的IPO。Arm的美国存托股票开盘价为每股56.1美元&#xff0c;比51美元IPO定价高出10%&#xff0c;随后稳步…

Talk | ICCV‘23北京通用人工智能研究院黄江勇:ARNOLD-三维场景中基于语言的机器人任务学习

本期为TechBeat人工智能社区第531期线上Talk&#xff01; 北京时间9月14日(周四)20:00&#xff0c; 北京通用人工智能研究院实习研究员—黄江勇的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “ARNOLD-三维场景中基于语言的机器人任务学习”&…

机器学习实战-系列教程8:SVM分类实战3非线性SVM(鸢尾花数据集/软间隔/线性SVM/非线性SVM/scikit-learn框架)项目实战、代码解读

&#x1f308;&#x1f308;&#x1f308;机器学习 实战系列 总目录 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 SVM分类实战1之简单SVM分类 SVM分类实战2线性SVM SVM分类实战3非线性SVM 4、非线性SVM 4.1 创建非线性数据 from sklearn.data…

奶牛个体识别 奶牛身份识别

融合YOLOv5s与通道剪枝算法的奶牛轻量化个体识别方法 Light-weight recognition network for dairy cows based on the fusion of YOLOv5s and channel pruning algorithm 论文链接 知网链接 DOI链接 该文章讨论了奶牛花斑、光照条件、不同剪枝方法、不同剪枝率对准确率的影响…

云原生Kubernetes:pod基础与配置

目录 一、理论 1.pod 2.pod容器分类 3.镜像拉取策略 4.pod 的重启策略 二、实验 1.Pod容器的分类 2.镜像拉取策略 三、问题 1.apiVersion 报错 2.pod v1版本资源未注册 3.格式错误 4.取行显示指定pod信息 四、总结 一、理论 1.pod (1) 概念 Pod是kubernetes中…