【Linux】共享内存

1.共享内存的概念

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。通信的前提是让两个进程看到同一份资源,信息的交流是建立在这个同一份资源上的,共享内存这种通信方式提供的资源或者平台是物理内存中的一块空间。首先在物理内存中申请一块空间,然后通过页表将这块空间映射到两个需要通信进程的进程地址空间,这样两个进程就可以对这块空间进行数据的写入和读取。

2.共享内存的创建

1.首先在物理地址中开辟好共享内存空间,供进程间通信使用。而且我们知道物理地址中的共享内存可能会有很多个,那么linux就要管理这些内存,管理的方法是先描述再组织,所以除了创建共享内存之外,还要为共享内存创建共享内存的内核数据结构。

2.将共享内存挂接到地址空间,本质上就是给两个进程之间的共享内存和虚拟地址空间之间建立映射,之后就可以开始进程间的数据传输与修改了。

3.用完之后要去掉共享内存和进程地址空间之间的联系,本质上就是修改页表,取消共享内存和虚拟内存的映射关系。

4.释放共享内存,将内存归还给系统。

3.函数接口

创建共享内存函数shmget()

key_t key是用来标识共享内存的,可以保证共享内存本身的唯一性
size_t size 表明需要申请空间的大小,单位是字节
int shmflg 是标志位,有两个参数IPC_CREAT 和IPC_EXCL这里的IPC_CREAT表示如果当前路径下不存在共享内存就创建一个新的共享内存,如果存在共享内存就直接使用该共享内存。后面的IPC_EXCL一般都和IPC_CREAT一起使用,两个标志位一起使用的时候就表示如果该路径下不存在共享内存就创建新的共享内存,如果存在共享内存就会报错,这样就可以保证我们永远使用的都是新创建的共享内存,这样就可以避免使用其他进程创建的共享内存而导致错误。

生成key的函数接口:

pathname路径名
proj_id 项目标识符

创建好key的值就可以创建共享内存了comm.hpp

服务端进程创建和销毁共享内存shm_server.cpp

客户端进程与被创建好的共享内存建立映射关系:shm_clienet.cpp

物理内存开辟好之后就要将物理内存映射到两个进程中

通过该函数就可以在物理内存中创建的共享内存关联到内存地址空间中,这样就可以使用一个指针指向这块内存地址空间了,直接在进程地址空间中修改数据就可以了。这里第一个参数就是上面我们创建的shmid,用来表示该块共享内存,第二个参数表示共享内存的地址,这里我们不需要管直接使用NULL让系统给我们分配就可以了,第三个表示标志位,使用0就可以了。

使用完共享内存后就需要断开挂接

断开挂接后需要释放共享内存将这块空间还给操作系统

4.使用共享内存完成通信:

这里实现的通信大致的步骤就是首先我们创建两个文件,用来表示两个进程,这里可以将两个文件分别取名为:shm_server.cpp和shm_client.cpp,之后在shm_server.cpp中我们首先使用ftok函数创建一个证明共享内存唯一性的key,之后通过该key值和shmget函数创建一个shmid来标识共享内存,然后使用shmat函数将物理地址中开辟的共享内存和进程地址空间进行关联,之后我们让shm_server.cpp读数据,然后通过shmdt函数取消关联和shmctl函数来删除共享内存。在client.c文件中我们也是按照上面的方式使用共享内存,之后我们往共享内存中写入数据,让shm_server.cpp读,之后我们就完成了通过共享内存来实现进程间通信,具体代码如下图:

comm.hpp

#ifndef _COMM_HPP_
#define _COMM_HPP_

#include <iostream>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <sys/ipc.h>
#include <sys/shm.h>

#define PATHNAME "."
#define PROJ_ID  0x66
// 共享内存的大小,一般建议是4KB的整数倍

#define MAX_SIZE 4097  

key_t getKey()
{
    key_t k = ftok(PATHNAME, PROJ_ID); //可以获取同样的一个Key!
    if(k < 0)
    {
       
        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);
}

int createShm(key_t k)
{
    return getShmHelper(k, IPC_CREAT | IPC_EXCL | 0600);
}

void *attachShm(int shmid)
{
   
    void *mem = shmat(shmid, nullptr, 0); //64系统,8
    if((long long)mem == -1L)
    {
        std::cerr <<"shmat: "<< errno << ":" << strerror(errno) << std::endl;
        exit(3);
    }
    return mem;
}

void detachShm(void *start)
{
    if(shmdt(start) == -1)
    {
        std::cerr <<"shmdt: "<< 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.cpp

#include "comm.hpp"
#include <unistd.h>

int main()
{
    key_t k = getKey(); 
    printf("key: 0x%x\n", k); // key
    int shmid = createShm(k);
    printf("shmid: %d\n", shmid); //shmid 

    // sleep(5);
    
    char *start = (char*)attachShm(shmid);
    printf("attach success, address start: %p\n", start);

    // 使用
    while(true)
    {
        // char buffer[]; read(pipefd, buffer, ...)
        printf("client say : %s\n", start);
        struct shmid_ds ds;
        shmctl(shmid, IPC_STAT, &ds);
        printf("获取属性: size: %d, pid: %d, myself: %d, key: 0x%x",\
                ds.shm_segsz, ds.shm_cpid, getpid(), ds.shm_perm.__key);
        sleep(1);
    }

    // 去关联
    detachShm(start);

    sleep(10);

    // 删除共享内存
    delShm(shmid);
    return 0;
}

shm_client.cpp

#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);

    char *start = (char*)attachShm(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)
    {
        sleep(5);
        snprintf(start, MAX_SIZE, "%s[pid:%d][消息编号:%d]", message, id, cnt++);
        
    }

    detachShm(start);

 

    return 0;
}

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

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

相关文章

Multisim14.3安装包下载及安装教程

[软件大小]: 888 MB [安装环境]: Win11/Win 10 [软件安装包下载]:https://pan.quark.cn/s/1c0217caf24a Multisim是美国国家仪器&#xff08;NI&#xff09;有限公司推出的以Windows为基础的仿真工具&#xff0c;适用于板级的模拟/数字电路板的设计工作 安装步骤 1.选中下载好…

自主AI能力加速企业智能化转型 | 爱分析报告

报告编委 黄勇 爱分析合伙人&首席分析师 孟晨静 爱分析分析师 外部专家&#xff08;按姓氏拼音排序&#xff09; 杜晨阳 力维智联 五维实验室主任 王哲 九章云极DataCanvas 雅图BU总经理 特别鸣谢&#xff08;按拼音排序&#xff09; 目录 1. 报告综述 2. 金融…

Java 3个常用工作流引擎

一&#xff1a;Java工作流框架是一种用于设计、执行和管理工作流程的技术。以下是几个常见的Java工作流框架&#xff1a; Activiti&#xff1a;Activiti是一款流行的开源Java工作流引擎&#xff0c;它基于BPMN 2.0标准&#xff0c;支持复杂的工作流程设计和管理。Activiti具有高…

Centos7 XFS(dm-0):Internal error XFS_WANT_CORRUPTED_GOTO

在k8s的道路上我们都是小白&#xff0c;每天启动虚机都会遇到各种各样的问题&#xff0c;这不 部署的k8s虚机启动发现操作系统启动异常&#xff0c;提示如下报错信息 XFS&#xff08;dm-0&#xff09;:Internal error XFS_WANT_CORRUPTED_GOTO at line 1700 of file fs/xfs/l…

【周末闲谈】文心一言,模仿还是超越?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 周末闲谈 ✨第一周 二进制VS三进制 文章目录周末闲谈前言一、背景环境二、文心一言&#xff1f;(_)?三、文心一言的优势&#xff1f;&#x1f617;&#x1f617;&#x1f617;四、文心一…

ADC选型关注的参数

目前&#xff0c;用来量化ADC动态性能的六个技术指标分别为SINAD&#xff08;信号与噪声失真比&#xff09;&#xff0c;ENOB&#xff08;有效位数&#xff09;&#xff0c;SNR&#xff08;信噪比&#xff09;&#xff0c;THD&#xff08;总谐波失真&#xff09;&#xff0c;TH…

ChatGPT原理解析

文章目录Transformer模型结构构成组件整体流程GPT预训练微调模型GPT2GPT3局限性GPT4相关论文Transformer Transformer&#xff0c;这是一种仅依赖于注意力机制而不使用循环或卷积的简单模型&#xff0c;它简单而有效&#xff0c;并且在性能方面表现出色。 在时序模型中&#…

GPT-4 介绍

1 简介 本文根据openAI的2023年3月的《GPT-4 Technical Report 》翻译总结的。 原文地址&#xff1a;https://arxiv.org/pdf/2303.08774.pdf 原文确实没有GPT-4 具体的模型结构&#xff0c;openAI向盈利组织、非公开方向发展了。也没透露硬件、训练成本、训练数据、训练方法等…

原生获取DOM节点

目录 一、通过document顶层方法获取 1、获取html标签 2、获取head标签 3、获取body标签 二、getElementBy系列获取 1、ID获取 2、类名获取 3、name属性获取 4、标签名获取 三、query系列获取 1、通过query选择器获取一个元素 2、通过querry选择器获取一组元素 四、通过…

特斯拉的操作系统是用什么语言编写的?

总目录链接>> AutoSAR入门和实战系列总目录 文章目录特斯拉车辆操作系统特斯拉GitHub中使用的语言Ruby和GoPythonSwift 和 Objective CQt我们知道操作系统至少需要一些非常低级的代码&#xff0c;这些代码在系统首次启动时运行&#xff0c;必须使用接近硬件的语言编写。…

如何使用python删除一个文件?好用到上头.....

人生苦短&#xff0c;我用python 若想利用python删除windows里的文件&#xff0c; 这里需要使用os模块 那接下来就看看利用os模块是如何删除文件的吧~ 具体实现方法如下&#xff01; 更多学习资料:点击此处跳转文末名片获取 os.remove(path) 删除文件 path. 如果path是一…

硬件语言Verilog HDL牛客刷题day02 组合逻辑部分

1.VL11 4位数值比较器电路 1.题目&#xff1a; 某4位数值比较器的功能表如下。请用Verilog语言采用门级描述方式&#xff0c;实现此4位数值比较器。 2.解题代码&#xff1a; timescale 1ns/1nsmodule comparator_4(input [3:0] A ,input [3:0] B ,output …

Cortex-A7常用汇编指令

Cortex-A7常用汇编指令 本节我们将介绍一些常用的 Cortex-A7汇编指令&#xff0c;如果想系统的了解 Cortex-A7的所有汇 编指令请参考《 ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf》的 A4章节。 处理器内部数据传输指令 使用处理器做的最多事情就是…

黑马点评笔记(自用)

1.优惠卷秒杀 &#xff08;1&#xff09;全局唯一ID 订单如果用自增&#xff0c;容易被猜到交易量&#xff0c;且数据量大的话分成多个表&#xff0c;都是自增&#xff0c;容易出现重复。所以用全局ID生成器&#xff0c;Redis独立自增不会重复&#xff0c;但安全性不保证&#…

Vue Nginx 配置跨域

1、方案1&#xff1a;Nginx配置跨域&#xff0c;Vue不用配置vite代理 1.nginx 配置SSL证书 listen *:443;server_name gitlab.xxxxxx.com;server_tokens off; ## Dont show the nginx version number, a security best practicessl on;ssl_certificate /etc/gitlab/xxxxxx.c…

俺的面试qwq

1.JavaScript的基本数据类型都有什么? 布尔型、数值型、字符串、数组、null、undefined、object、symbol 2.数组方法pop()push() unshift() shift()的作用? pop()删除最后一个元素、push()在数组最后增加元素、unshift()在数组最前面增加元素、shift()删除第一个元素 3.box-s…

【ChatGPTAIGC研讨社】“iPhone时刻”:未来已来

文章目录前言一、ChaGPT&AIGC研讨社简介二、ChatGPT&AIGC研讨社的优势1.丰富充实的资料库Github开源&#xff1a;[ChatGPT_Project](https://github.com/shawshany/ChatGPT_Project)飞书资料库2.重量级嘉宾3.工作机会4.投资资源总结前言 去年年末&#xff0c;ChatGPT以…

Linux编译器-gcc/g++ 使用

在介绍gcc/g的使用前我们先了解一下两者的不同 gcc时主要编译c语言&#xff0c;而g主要编译c的&#xff0c;但是两者的选项是相同的&#xff0c;因此我们以gcc和c语言为例来讲解。背景知识 gcc和g都是编译器其核心作用将文本类文件翻译成二进制可执行 那么其过程是怎样的&…

dolphinscheduler 2.0.6 资源中心改造方案二:通过NFS挂载共享目录

目录调度资源中心存储概要安装NFS服务器客户端调度验证关闭SFTP开关&#xff08;可忽略&#xff09;重新上传资源文件worker执行任务验证服务器woker客户端worker其它nfs共享目录的配置文件/etc/exports说明调度资源中心存储概要 针对现有的单机存储可以做哪些扩展&#xff1f;…

免费1年服务器,部署个ChatGPT专属网页版

作者&#xff1a;小傅哥 博客&#xff1a;https://bugstack.cn 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; 白皮袄个免费1年服务器&#xff0c;部署个ChatGPT专属网页版&#xff01; api.openai.com port 443: Connection timed out 你是…