Linux--进程间的通信-共享内存

前文:
Linux–进程间的通信-匿名管道
Linux–进程间的通信–进程池
Linux–进程间的通信-命名管道

共享内存

对于两个进程,通过在内存开辟一块空间(操作系统开辟的),进程的虚拟地址通过页表映射到对应的共享内存空间中,进而实现通信

特点和作用:

  1. 高效性: 共享内存是一种高效的进程间通信方式,因为它允许多个进程直接访问同一块内存,而无需进行复制或数据传输。
  2. 快速通信: 由于共享内存直接映射到进程的地址空间,因此读写速度快,适用于对通信速度有较高要求的场景。
  3. 灵活性: 共享内存提供了一种灵活的通信方式,允许多个进程在需要时访问共享数据,而无需通过中间介质进行通信。
  4. 数据共享: 多个进程可以通过共享内存实现数据共享,从而实现对数据的共同读写和处理。

模拟实现

在这里插入图片描述
在这里插入图片描述

代码

Comm.hpp:包含共享内存的创建,销毁,挂接进程等。

#pragma once

#include<stdio.h>
#include<iostream>
#include<string>
#include<cerrno>
#include<cstring>
#include<cstdlib>
#include<sys/ipc.h>
#include<sys/types.h>
#include<sys/shm.h>
using namespace std;


const char* pathname="/home/ubuntu/Learning/Pipe";
const int proj_id=0x66;

//在内核中,共享内存的基本单位是4kb,我们申请的大小相当于是n*4kb
const int DefaultSize=4096;

//将key值转换为16进制的;
string ToHEX(key_t k)
{
    char buffer[1024];
    snprintf(buffer,sizeof(buffer),"0x%x",k);
    return buffer;
}

//获取键值
key_t GetShmKeyorDie()
{
    key_t k=ftok(pathname,proj_id);
    if(k<0)
    {
        //当返回值为-1时,错误表示stat(2)系统调用错误
        cerr << "ftok error, errno : " << errno << ", error string: " << strerror(errno) << endl;
        exit(1);
    }
    return k;
}

//创建共享内存,只在该函数内调用
int CreateShmOrDie(key_t key,int size,int flag)
{
    int shmid = shmget(key,size,flag);
    if(shmid<0)
    {
        std::cerr << "shmget error, errno : " << errno << ", error string: " << strerror(errno) << std::endl;
        exit(2);
    }
    return shmid;

}

//调用时的创建共享内存
int CreateShm(key_t key,int size)
{
    //如果已经存在了,那么会报错;
    return CreateShmOrDie(key,size,IPC_CREAT|IPC_EXCL|0666);
}
//调用时的获取
int GetShm(key_t key,int size)
{
    return CreateShmOrDie(key,size,IPC_CREAT);
}

//删除共享内存
void DeleteShm(int shmid)
{
    int n=shmctl(shmid,IPC_RMID,nullptr);
    if(n<0)
    {
        cerr<<"shmctl error"<<endl;
    }
    else
    {
        cout<<"shmctl delete shm success, shmid: "<<shmid<<endl;
    }
}

//查看共享内存的状态
void ShmDebug(int shmid)
{
    struct shmid_ds shmds;
    int n=shmctl(shmid ,IPC_STAT,&shmds);
    if(n<0)
    {
        std::cerr << "shmctl error" << std::endl;
        return;
    }
    std::cout << "shmds.shm_segsz: " << shmds.shm_segsz << std::endl;
    std::cout << "shmds.shm_nattch:" << shmds.shm_nattch << std::endl;
    std::cout << "shmds.shm_ctime:" << shmds.shm_ctime << std::endl;
    std::cout << "shmds.shm_perm.__key:" << ToHEX(shmds.shm_perm.__key) << std::endl;
}

void* ShmAttach(int shmid)
{
    void* addr = shmat(shmid,nullptr,0);
    //第二个参数设置nullptr,表示让系统选择合适的地址进行连接
    if((long long int)addr==-1)
    {
        cerr<<"shmat error"<<endl;
        return nullptr;
    }
    return addr;
}

void ShmDetach(void* addr)
{
    int n=shmdt(addr);
    if(n<0)
    {
        cerr<<"shmdt error"<<endl;
    }
}

fifo.hpp:利用管道来实现对共享内存实现同步机制。

#include<iostream>
#include<string>
#include<cstring>
#include<cerrno>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<assert.h>
using namespace std;

#define Mode 0666
#define Path "./fifo"

class fifo
{
public:
    fifo(const string & path=Path)
    :_path(path)
    {
        umask(0);
        int n=mkfifo(_path.c_str(),Mode);
        if(n==0)
        {
            cout<< "mkfifo success" << endl;
        }
        else
        {
            cerr << "mkfifo failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
        }
    }
    ~fifo()
    {
        int n=unlink(_path.c_str());
        if (n == 0)
        {
            cout << "remove fifo file " << _path << " success" << endl;
        }
        else
        {
            cerr << "remove failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;
        }
    }
private:
    string _path; //文件路径
};

class Sync
{
public:
    Sync()
    :_rfd(-1),
    _wfd(-1)
    {}
    void OpenReadOrDie()
    {
        _rfd=open(Path,O_RDONLY);
        if(_rfd<0)
            exit(1);
    }
    void OpenWriteDie()
    {
        _wfd=open(Path,O_WRONLY);
        if(_wfd<0)
            exit(1);
    }
    bool Wait()
    {
        bool ret=true;
        uint32_t c=0;
        ssize_t n=read(_rfd,&c,sizeof(uint32_t));
        if(n==sizeof(uint32_t))
        {
            cout<<"server wakeup ,begin read shm..."<<endl;
        }
        else if(n==0)
        {
            ret=false;
        }
        else
        {
            return false;
        }
        return ret;
    }
    void Wakeup()
    {
        uint32_t c=0;
        ssize_t n=write(_wfd,&c,sizeof(c));
        assert(n==sizeof(uint32_t));

        cout<<"wakeup server..."<<endl;
    }
    ~Sync() {}
private:
    int _wfd;
    int _rfd;
};

ShmServer.cc

#include "Comm.hpp"
#include "fifo.hpp"
#include<unistd.h>
int main()
{
    
    //1.获取key
    key_t key = GetShmKeyorDie();
    std::cout << "key: " << ToHEX(key) << std::endl;
    // sleep(2);
    
    //2.创建共享内存
    int shmid = CreateShm(key, DefaultSize);
    std::cout << "shmid: " << shmid << std::endl;
     sleep(2);
  

    //4.将共享内存与进程挂接
    char* addr=(char*)ShmAttach(shmid);
    cout<<"Attach shm success, addr: "<<ToHEX((uint64_t)addr)<<endl;
   
    //0.先引入管道
    fifo ff;
    Sync syn;
    syn.OpenReadOrDie();

   //进行通信
     while(1)
     {
        if(!syn.Wait())break;
        cout<<"shm content: "<<addr<<endl;
     }

    ShmDetach(addr);
    std::cout << "Detach shm success, addr: " << ToHEX((uint64_t)addr) << std::endl;
     
     
    //3.删除共享内存
    DeleteShm(shmid);
    return 0;
}

ShmClient.cc

#include"Comm.hpp"
#include "fifo.hpp"
#include<unistd.h>
int main()
{
    key_t key = GetShmKeyorDie();
    std::cout << "key: " << ToHEX(key) << std::endl;
    // sleep(2);

    int shmid = GetShm(key, DefaultSize);
    std::cout << "shmid: " << shmid << std::endl;
    
    
    char* addr=(char*)ShmAttach(shmid);
    cout<<"Attach shm success, addr: "<<ToHEX((uint64_t)addr)<<endl;
    
    
    //通信
    memset(addr,0,DefaultSize);
    Sync syn;
    syn.OpenWriteDie();
    for(char c ='A';c<='Z';c++)
    {
        addr[c-'A']=c;
        sleep(1);
        syn.Wakeup();
    }

    ShmDetach(addr);
    std::cout << "Detach shm success, addr: " << ToHEX((uint64_t)addr) << std::endl;
    
    return 0;
}

解释

获取键值和创建共享内存

在这里插入图片描述

如果ftok函数返回失败时,我们就需要不断的尝试,对路径名和id值进行修改,直至成功。一般来说,有几种可能:

  • 1:如果传入的路径名不存在
  • 2:传入的路径名没有读取权限,无法读取该文件的索引节点号
  • 3:文件的索引节点超过了8位,即超过了一个字节的范围
  • 4:系统中已经使用了所有的IPC键值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

删除共享内存

在这里插入图片描述
在这里插入图片描述

查看共享内存的状态

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

挂接进程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

进入通信

在这里插入图片描述

协同机制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

# 从浅入深 学习 SpringCloud 微服务架构(三)注册中心 Eureka(3)

从浅入深 学习 SpringCloud 微服务架构&#xff08;三&#xff09;注册中心 Eureka&#xff08;3&#xff09; 段子手168 1、eureka&#xff1a;高可用的引入 Eureka Server 可以通过运行多个实例并相互注册的方式实现高可用部署&#xff0c; Eureka Server 实例会彼此增量地…

文件批量高效重命名,支持重命名后不满意恢复原名,高效管理文件

我们每天都会与大量的文件打交道&#xff0c;无论是工作文件、学习资料&#xff0c;还是生活照片、视频&#xff0c;都需要我们进行高效的文件管理。然而&#xff0c;传统的文件重命名方式往往效率低下&#xff0c;无法满足我们的需求。今天&#xff0c;我们为您带来了一款批量…

MATLAB设置变量

您可以通过简单的方式分配变量。例如&#xff0c; 示例 x 3 %定义x并用值初始化它 MATLAB将执行上述语句并返回以下结果- x 3 它创建一个名为x的1乘1矩阵&#xff0c;并将值3存储在其元素中。再举一个实例&#xff0c; 示例 x sqrt(16) %定义x并用表达式初始化它 MATLAB将…

cv2技术原理-图像旋转原理及手动实现

cv2技术原理-图像旋转原理及手动实现 1、图像旋转opencv实现2、cv2.getRotationMatrix2D函数解释3、数学原理推导旋转矩阵M4、手动计算旋转矩阵M5、旋转矩阵M的使用6、使用旋转矩阵M手动实现旋转功能 1、图像旋转opencv实现 图像旋转在对数据集数据增强&#xff08;主要是随机…

WordPress自动记录404死链方法+实用代码

WordPress自动记录404死链方法实用代码 WordPress自动将404死链记录到TXT文档中 在网站根目录新建文件&#xff1a; 404.txt&#xff0c;并设置权限为&#xff1a;755 将以下代码粘贴到你的 WordPress 主题中的 404.php $error_url https://.$_SERVER[HTTP_HOST].$_SERVER[…

python爬虫小案例——汽车之家

本篇文章是使用bs4中的BeautifulSoup和requests解析网页和获取数据&#x1f451;&#x1f31f; 文章目录 &#x1f31f;前言一、&#x1f349;bs4中的BeautifulSoup二、&#x1f349;bs4的语法三、&#x1f349;内容实践1. 确定想要爬取的内容2. 分析网页3. 获取数据分析 &…

【微服务】spring读取配置文件多种方式深入详解

目录 一、前言 二、java配置文件介绍 2.1 java配置文件产生原因 2.2 项目使用配置文件好处 2.3 springboot项目配置文件的必要性 2.4 微服务架构下配置文件使用场景 三、java读取配置文件常用方法 3.1 使用Properties类读取配置文件 3.1.1 使用getResourceAsStream读取…

【C语言】操作符相关编程题

目录 题目一&#xff1a; 题目二&#xff1a; 题目三&#xff1a; 题目三&#xff1a; 题目四&#xff1a; 题目五&#xff1a; 题目六&#xff1a; 题目七&#xff1a; 题目八&#xff1a; 题目一&#xff1a; 题目&#xff1a;不创建临时变量&#xff0c;交换两个数…

代码托管基础操作

在待上传代码文件夹中右键&#xff0c;打开Git Bash Here依次输入以下命令&#xff1a; git init(在本地初始化一个代码仓库&#xff0c;具体表现为会在你的文件夹里出现一个隐藏的.git文件夹) git add .&#xff08;先把代码放到本地的一个缓冲区&#xff09;添加当前目录下的…

Windows使用freeSSHd搭建sftp服务器

一、安装 1、运行freeSSHd.exe&#xff08;最好以管理员方式运行&#xff09; 2、选择安装位置 3、选择全部安装 4、是否创建开始启动栏快捷入口 5、是否创建桌面快捷方式 6、安装 7、安装完成&#xff0c;点击close 8、安装私钥 9、是否要安装为服务 10、全部安装完成 二、配…

查找输入整数的二进制中1的个数

方法1&#xff1a;简单做法&#xff0c;直接用库函数 #include<bitset> #include<iostream> using namespace std; int main(){int n;while(cin>>n){bitset<32> b(n);cout<<b.count()<<endl;} }补充bitset //注意&#xff1a;直接输出 b…

EasyExcel导出图片并实现动态表头、自动合并单元格、给指定单元格设置值

概要描述 最近工作中涉及到使用Excel导出图片的需求,下面对使用Excel导出图片遇到的一些问题进行记录说明。需求通过 EasyExcel中提供的转换器(Converter)和拦截器(Handler)实现。EasyExcel 官网地址 实现效果 实现过程 EasyExcel 支持导出 ByteArray、File、String、In…

软件缺陷和测试用例

软件缺陷 软件缺陷概念 Bug有时也被泛指因软件产品内部的缺陷引起的软件产品最终运行时和预期属性的偏离。 产生原因 1.需求不明确2.软件结构复杂3.编码问题4.项目期限短5.使用新技术 类型 错误、遗漏、额外实现 准则 Correct&#xff08;准确&#xff09;&#xff1a;…

一堆喷儿香喷儿香的工具网站-已经收藏-搜嗖工具箱!

文心一言 https://yiyan.baidu.com/ ​ ChatGpt横空出世的横空出世好像一把钥匙&#xff0c;开启了大模型时代&#xff0c;国内也有不错的产品&#xff0c;比如百度的文心一言&#xff0c;从3.5到4.0看得见的成长&#xff0c;现在的文心一言是我们工作中不可缺少的好帮手&am…

基于单片机的智能病床呼叫系统设计与仿真

摘 要 本文设计的病床呼叫系统采用单片机作为控制器。该系统具有远程控制、病人的身体情况检测、报警呼叫、显示和执行器运动的功能。远程控制由红外线传感器和矩阵键盘组成&#xff0c;检测电路由温湿度传感器DH22、心率传感器Pulse Sensor、压力传感器MPX4115组成&#x…

uniapp 如何区分目前运行环境(app、web、mp-weixin)

platform 区分 iOS、Android uniplatform 区分 app、web、mp-weixin ....

JavaEE 初阶篇-深入了解 File 文件操作(实现文件搜索、非空文件夹删除)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 File 文件概述 2.0 创建 File 类对象的方法 2.1 判断文件类型、获取文件信息的方法 2.2 创建文件、删除文件的方法 2.3 遍历文件夹的方法 3.0 文件搜索与删除 3.1…

学习笔记<2024.4.15-2024.4.21>:Attention Is All You Need

Transformer中Self-Attention以及Multi-Head Attention详解 (https://www.bilibili.com/video/BV15v411W78M/?spm_id_from333.337.search-card.all.click&vd_sourcef32decb03075b4a1833fe5c47c11ba94)

在线拍卖系统,基于SpringBoot+Vue+MySql开发的在线拍卖系统设计和实现

目录 一. 系统介绍 二. 功能模块 2.1. 管理员功能模块 2.2. 用户功能模块 2.3. 前台首页功能模块 2.4. 部分代码实现 一. 系统介绍 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系…

Axure琐碎细节

文章目录 琐碎细节注释预览编写原型图的时候可以把颜色改为灰色标尺竖直文字左对齐Axure中的文字怎么添加元件层级问题如何找到各种各样的形状&#xff0c;比如三角形了 五角星了 十字架了给按钮设置简单的交互动作通过锁来等比例缩放 琐碎细节 注释 有时候我们需要给我们的元…