【进程间通信】共享内存

文章目录

  • 共享内存
    • 常用的接口
    • 指令
    • 利用命名管道实现同步机制
    • 总结

System V的IPC资源的生命周期都是随内核的。

共享内存

共享内存也是为了进程间进行通信的,因为进程间具有独立性,通信的本质是两个不同的进程看到同一份公共资源,所以共享内存一定是由OS提供的,共享内存的本质就是,在内存中开辟一块空间,然后映射在需要通过这片空间的进程的地空间中堆和栈之间共享区,通过这样的方式让两个不同的进程看到同一份公共资源。如下图:
在这里插入图片描述
一个共享内存可以满足很多进程进行通信,它可以挂载很多进程,但是OS中的进程是很多的,不同的进程和不同的进程之间需要通信的内容和方式也不太一样,所以OS中一定会存在大量的共享内存,因此OS一定要对共享内存进行管理(先描述,在组织),所以OS中一定有描述共享内存的各种属性的结构体,然后用链表等数据结构把OS中存在的共享内存管理起来,这样对共享内存的管理就变成了对链表的增删查改。
在这里插入图片描述

那么如何保证两个不同进程能看到同一个共享内存呢?
OS是让两个进程通过约定的方式让不同的进程看到同一块共享内存,两个进程约定一个key值,这个key值会被写入shm结构体中,然后不同的进程拿着相同的key值,就可以看到同一份共享内存了,但是系统中的共享内存会存在很多个,这个key值每个共享内存应该是不同的,所以我们需要尽可能的保证key的唯一性,但是让用户来进行这个操作,明显是不靠谱的,所以有个系统调用的函数,可以来帮助我们形成这个key值。
在这里插入图片描述
只需要传进去一个字符串和一个整型变量,这个函数就会通过自身的算法给我们形成一个key值,两个不同的进程拿着相同的字符串和相同的整型变量再通过相同的算法,形成的key值一定是一样的。这个key值最终是要被写进内核数据结构的。
在这里插入图片描述
这个__key就是我们用户自己传进去的key。共享内存 = 共享内存空间 + 共享内存属性

常用的接口

shmget
在这里插入图片描述
第一个参数就是我们之前自己形成的key,最后一个最常用的标志位就两个,IPC_CREAT和IPC_EXCL

  1. IPC_CREAT :不存在就创建,存在就获取
  2. IPC_EXCL:单独使用没有任何意义,和IPC_CREAT 一起使用,不存在就创建,存在就报错,这两个参数一起使用可以保证一定是第一次创建共享内存。

第三个参数的标志位后面可以直接跟共享内存的权限,具体可以参考下面的代码。

它的返回值就类似于文件描述符,方便用户操作,并且后面的节后都需要用这个shmid来标识自己创建的共享内存,我们的key是内核里面用的为了标识共享内存的唯一性,我们用户用的都是shmid,并且指令删除共享内存也是要用shmid不能使用key。

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

创建成功后,我们会拿到一个指针,这个指针就和malloc开辟的空间一样,可以直接拿着指针对这块内存进行操作。第二个参数我们一般为nullptr就行,最后一个参数一般为0。

shmdt
在这里插入图片描述

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

指令

常用相关的函数就是这些,在Linux中如果我们要查看已经创建的共享内存有哪些,可以使用ipcs -m 指令
在这里插入图片描述
想要删除一个共享内存可以使用ipcrm -m shmid 的方式删除
在这里插入图片描述
最后的数字应该为具体的shmid。

利用命名管道实现同步机制

共享内存不会提供同步机制,但是他是需要同步机制的,我们可以使用管道来实现它的同步机制,接下来我们可以利用前面的命名管道尝试实现一下这个同步机制。

我们需要两个独立的进程一个server,一个client,所以我们需要一个可以形成两个可执行程序的Makefile。

.PHONY:all
all:client serverclient:Client.ccg++ -o $@ $^ -std=c++11server:Server.ccg++ -o $@ $^ -std=c++11.PHONY:clean
clean:rm -rf client server

然后我们需要一个Client.cc和Server.cc,但是我们需要形成同一个key,所以我们可以把两个源文件中需要两个进程看到的同一份资源抽出来,Com.hpp。

Com.hpp

#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>const std::string path = "/home/ysl/long/class_dragon/test_5_8/shm";
const std::string filename = "fifo";
const int proj_id = 0x11223344;
const int num = 4096;key_t getkey()
{key_t key = ftok(path.c_str(), proj_id);if(key < 0){std::cerr << "getkey error" << std::endl;exit(-1);}return key;
}int _getshm(key_t key, int flag)
{int shmid = shmget(key,num,flag);if(shmid < 0){std::cerr << "shm error" << std::endl;exit(-1);}return shmid;
}   int Create_shm(key_t key)
{return _getshm(key,IPC_CREAT|IPC_EXCL|0644);
}int getshm(key_t key)
{return _getshm(key,IPC_CREAT);
}bool Create_fifo()
{int n = mkfifo(filename.c_str(),0666);if(n < 0){std::cerr << "mkfifo error" << std::endl;return false;}return true;
}

Server.cc

#include "Com.hpp"class Init
{
public:Init(){//创建命名管道Create_fifo();// 获取keykey_t key = getkey();// 创建共享内存shmid = Create_shm(key);std::cout << shmid << std::endl;std::cout << "chuangjian" << std::endl;// 挂载addr = (char *)shmat(shmid, nullptr, 0);std::cout << "guazai" << errno << std::endl;fd = open(filename.c_str(),O_RDONLY);}~Init(){shmdt(addr);std::cout << "qu" << std::endl;// 删除共享内存shmctl(shmid, IPC_RMID, nullptr);std::cout << "shan" << std::endl;close(fd);unlink(filename.c_str());}public:int shmid;char *addr;int fd;
};Init init;
int main()
{while(true){int code = 0;ssize_t n = read(init.fd,&code,sizeof code);if(n > 0){std::cout << init.addr << std::endl;}else if(n == 0){break;}//sleep(1);}return 0;
}

Client.cc

#include "Com.hpp"class Init
{
public:Init(){// 获取keykey_t key = getkey();// 创建共享内存shmid = getshm(key);// 挂载addr = (char *)shmat(shmid, nullptr, 0);}~Init(){shmdt(addr);}public:int shmid;char *addr;
};Init init;int main()
{int fd = open(filename.c_str(),O_WRONLY);for(char ch = 'a'; ch <= 'z'; ++ch){int code = 1;write(fd,&code,sizeof code);init.addr[ch-'a'] = ch;sleep(1);}return 0;
}

我们是可以通过命名管道让共享内存拥有同步机制的。

总结

  1. 共享内存的通信方式,不会提供同步机制,共享内存是直接裸露给所有的使用者的,所以一定要注意共享内存的使用安全问题。
  2. 共享内存可以提供较大的空间。
  3. 共享内存是所有进程间通信中速度最快的。可以减少数据拷贝的次数。

为什么说共享内存是最快的?
这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据,也就会减少很多的数据的拷贝。

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

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

相关文章

记录些大模型题集(2)

请简述Transformer基本原理Transformer模型是基于自注意力机制的深度学习模型,主要应用于自然语言处理领域。其基本原理可以概括为以下几个核心组成部分: 自注意力机制(Self-Attention Mechanism)自注意力机制是Transformer的核心概念,它允许模型在进行编码时能够考虑到输…

Java 11 到 Java 8 的兼容性转换

Java 11 到 Java 8 的兼容性转换 欲倚绿窗伴卿卿&#xff0c;颇悔今生误道行。有心持钵丛林去&#xff0c;又负美人一片情。 静坐修观法眼开&#xff0c;祈求三宝降灵台&#xff0c;观中诸圣何曾见&#xff1f;不请情人却自来。 入山投谒得道僧&#xff0c;求教上师说因明。争奈…

Spring Bean的线程安全问题

对于Proptotype&#xff08;原型&#xff09;作用域 普通成员变量是否线程安全。 安全 静态变量线程是否安全。 不安全 对于singletion&#xff08;单例&#xff09;作用域 普通成员变量是否线程安全。 不安全 静态变量线程是否安全。 不安全 如何解决 对于单例模式&…

WordPress MasterStudy LMS插件 SQL注入漏洞复现(CVE-2024-1512)

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 0x02 漏洞概述 WordPress Plugin MasterStudy LMS 3.2.5 版本及之…

java项目之在线课程管理系统源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的在线课程管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 在线课程管理系统的主要…

Nginx配置/.well-known/pki-validation/

当你需要在Nginx上配置.well-known/pki-validation/时&#xff0c;这通常是为了支持SSL证书的自动续订或其他验证目的。以下是配置步骤&#xff1a; 创建目录结构&#xff1a; 在你的网站根目录下创建一个名为.well-known的目录&#xff08;SSL证书申请之如何创建/.well-known/…

Linux环境Redis部署

Redis部署 Redis是一个高性能的开源键值存储系统&#xff0c;它主要基于内存操作&#xff0c;但也支持数据的持久化。与其他数据库相比&#xff0c;Redis的主要优势在于它的高性能、丰富的数据结构和原生的持久化能力。Redis不仅提供了类似的功能&#xff0c;还增加了持久化和…

如何实现本地缓存

什么是本地缓存 本地缓存是一种数据存储技术&#xff0c;它将数据暂时存储在本地的物理内存&#xff08;如RAM&#xff09;或者其他快速访问的存储介质中&#xff0c;以便快速检索&#xff0c;减少对远程数据源&#xff08;如数据库或外部API&#xff09;的访问需求。这种技术能…

[初阶数据结构】单链表

前言 &#x1f4da;作者简介&#xff1a;爱编程的小马&#xff0c;正在学习C/C&#xff0c;Linux及MySQL。 &#x1f4da;本文收录于初阶数据结构系列&#xff0c;本专栏主要是针对时间、空间复杂度&#xff0c;顺序表和链表、栈和队列、二叉树以及各类排序算法&#xff0c;持…

Java基础(23)三次握手和四次挥手

TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议。为确保数据的可靠传输&#xff0c;TCP使用了一系列的控制机制&#xff0c;包括三次握手和四次挥手。这些机制确保了连接的建立、数据…

如何使用client-go构建pod web shell

代码示例及原理 原理是利用websocket协议实现对pod的exec登录&#xff0c;利用client-go构造与远程apiserver的长连接&#xff0c;将对pod容器的输入和pod容器的输出重定向到我们的io方法中&#xff0c;从而实现浏览器端的虚拟终端的效果消息体结构如下 type Connection stru…

Meta更低的训练成本取得更好的性能: 多token预测(Multi-Token Prediction)

Meta提出了一种透过多token预测(Multi-token Prediction)来训练更好、更快的大型语言模型的方法。这篇论文的重点如下: 训练语言模型同时预测多个未来的token,可以提高样本效率(sample efficiency)。 在推论阶段,使用多token预测可以达到最高3倍的加速。 论文的主要贡献包括: …

Django中如何使用WebSocket实时更新数据?

在Django中使用WebSocket实时更新数据&#xff0c;可以通过使用第三方库Django Channels实现。Django Channels是基于WebSocket的实时通信框架&#xff0c;它使得Django应用可以处理实时的、异步的任务。 下面是使用Django Channels实时更新数据的一般步骤&#xff1a; 安装D…

ES集群数据备份与迁移

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、文章涉及概念讲解二、操作步骤1.创建 snapshot repository操作主机hadoop1分别操作从机hadoop2和hadoop3 2. 查看仓库信息3. 备份索引&#xff0c;生成快照…

【S32K UDS BootLoader】-1.1-Unified bootloader Demo和ECUBus工具的使用

<--返回「Autosar_MCAL高阶配置」专栏主页--> 目录 1 下载S32K1/S32K3/S12Z Unified bootloader Demo 1.1 在S32DS中编译S32K312_CAN_bootloader_RTD2d0工程并烧录 2 ECUBus工具使用 2.1 PCAN环境搭建 1.1.1 安装PCAN驱动 1.1.2 安装PCAN-View 2.2 下载并安装ECU…

蓝桥杯 BASIC-26 基础练习 报时助手

蓝桥杯 BASIC-26 基础练习 报时助手 问题描述 给定当前的时间&#xff0c;请用英文的读法将它读出来。 时间用时h和分m表示&#xff0c;在英文的读法中&#xff0c;读一个时间的方法是&#xff1a; 如果m为0&#xff0c;则将时读出来&#xff0c;然后加上“o’clock”&#xff…

嵌入式C语言的变量和函数存储类型

目录 概述 1 嵌入式C的数据类型 2 嵌入式C语言存储类型 2.1 auto存储类型 2.2 extern存储类型 2.3 register存储类型 2.4 static存储类型 概述 本文主要介绍嵌入式C语言中的数据变量的类型&#xff0c;包括其数据长度&#xff0c;在内存中的存储方式。还介绍了数据的存储…

C语言 | Leetcode C语言题解之第77题组合

题目&#xff1a; 题解&#xff1a; int** combine(int n, int k, int* returnSize, int** returnColumnSizes) {int* temp malloc(sizeof(int) * (k 1));int tempSize 0;int** ans malloc(sizeof(int*) * 200001);int ansSize 0;// 初始化// 将 temp 中 [0, k - 1] 每个…

Vue项目中使用echarts教程

Vue项目中使用echarts教程 步骤npm 安装ECharts引入 ECharts老版本引入方式 &#xff08;v4版本&#xff09;新版本引入方式 &#xff08;v5版本&#xff09; ECharts初体验ECharts组件化&#xff08;进阶写法&#xff09; 步骤 npm 安装ECharts npm install echarts --save引…

回答篇:测试开发高频面试题目

引用之前文章&#xff1a;《测试开发高频面试题目》 https://blog.csdn.net/qq_41214208/article/details/138193469?spm1001.2014.3001.5502 本篇文章是回答篇&#xff08;持续更新中&#xff09; 1. 什么是测试开发以及其在软件开发流程中的作用。 a. 测试开发是指测试人员或…