Linux基础内容(20)—— 共享内存

news2024/11/20 9:31:41

Linux基础内容(19)—— 进程间通信(介绍与管道内容)_哈里沃克的博客-CSDN博客

目录

1.共享内存的原理

2.共享内存的概念和特点

创建共享内存 

共享内存的形式

共享内存(ipc资源)的调用和特征

用户接口删除共享内存

共享内存关联

去关联

特点

共享内存大小


1.共享内存的原理

1.由于进程本身的结构 --- 虚拟内存地址空间,使得进程间互相看不见对面的物理内存地址,达不到进程间直接通信的目的

2.但如果OS能提供一个接口,这个接口是用户调用之可以构建出共享的内存,并且共享内存的地址通过页表映射到虚拟地址空间中,两个进程如果都这里映射了同一个共享内存,那么就可以达到进程间通信的目的

 3.如果不想通信了,需要切断两边的映射(去关联)和释放共享内存

理解:

1.进程间通信是专门设计的,用户只需要调用接口

2.共享内存是一种通信方式,所有想通信的进程都可以用

3.OS中一定可能同时存在多个共享内存

2.共享内存的概念和特点

通过让不同的进程看到同一块内存块,这样的内存称之为共享内存

创建共享内存 

size:申请多大的共享内存

key:能进行唯一性表示的数,具体内容不重要,看到同一个key就可以看到同一个资源了

shmflg:

IPC_CREAT -- 指定的共享内存,不存在,创建;存在,共享内存标志返回

IPC_EXCL -- 无法单独使用;只有当 IPC_CREAT|IPC_EXCL 同时使用,如果不存在,创建,如果存在,出错返回

返回值:成功返回共享内存的标识符,失败返回-1

注意:创建时还得把共享内存的权限属性给传入

转换得到key值

pathname:一个字符串

proj_id:一个数字

这样组合出唯一的数字key返回

返回:成功返回key值,失败-1

共享内存的形式

1.c语言中malloc函数需要输入大小,但是free反而不需要。这是因为malloc函数不会只给我们申请指定大小空间,它一定要申请更大的空间来存储它的属性方便管理

2.关于以前进程的也是先描述再组织

3.那么对于共享内存,也是如此,我们不会只申请指定大小就结束了,我们还会存储共享内存的相关属性,这样方便管理,那么对于共享内存而言:物理内存存储块+共享内存属性

4.上面说过,共享内存可能有很多,那么如何表示唯一性呢?答案很明显,key就是唯一的,那么创建时我们能通过key得到唯一的共享内存。

5.那么key也是一种属性,所以这个key也被放在描述共享内存的属性之中。

6.那么链接共享内存就是通过得到一样的key,在组织数据结构中遍历找每个内存属性中放key的值,找到了就唯一指定了,key是内核级别的属性

7.shmid和key的关系是:shmid是在用户级别调用的数值。其区别就于fd和inode类似,inode内核级别表示文件的唯一性,而用户直接不使用inode,而是调用函数返回的fd进行操作

共享内存(ipc资源)的调用和特征

1.共享内存的生命周期随着OS的,不随进程而消除(system V特性)

 2.ipcs -m查看共享内存

perm:文件权限

nattch:关联的进程

3.ipcrm -m shmid删除共享内存

3.ipcs -q查看消息队列

4. ipcs -s查看信号量

用户接口删除共享内存

该接口是对共享内存进行控制,控制里包括删除

shmid:指定shmid

cmd:指令

IPC_STAT

IPC_SET

IPC_RMID:立即移除共享内存

buf:获取属性存储空间,不要则输入nullptr

返回值:失败则-1

删除该共享内存的前提就是将内存与进程相关联,毕竟调用系统接口删除的前提是有这块地址

共享内存关联

用于映射到虚拟地址空间的哪个位置中

后两位数指定位置,一般不指定:设为nullptr和0

返回值:共享内存地址空间的返回值

失败是返回-1

去关联

shmdt()

 返回0成功,-1失败

特点

优点:所以进程间通信中速度最快的

因为我们写入共享内存,另一方就能得到,能大大减少拷贝的次数

同样的代码用来通信,(单纯的收发消息)需要拷贝几次才能完成任务:

管道实现:4+2次

共享内存实现:2+2次

缺点:不给我们进行同步互斥消息的,没有对数据做任何保护

共享内存大小

建议是4KB的整数倍

因为系统分配共享内存是以4KN为单位的 -- 内存划分内存块的基本单位

给大给小都会向上取整:使用的内存显示为申请的,但是内存中的确开辟,只是用户调不到

comm.hpp
#ifndef _COMM_HPP_
#define _COMM_HPP_

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

#define PATHNAME "."
#define PROJ_ID 0x66
#define MAX_SIZE 4096

key_t getKey()
{
    key_t k = ftok(PATHNAME, PROJ_ID);
    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 creatShm(key_t k)
{
    return getShmHelper(k, IPC_CREAT | IPC_EXCL | 0600); // 创建一个新的,所以如果没有就判错
}

int getShm(key_t k)
{
    return getShmHelper(k, IPC_CREAT /*0*/); // 调用创建的,0也可以
}

void* attchShm(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 deleteShm(int shmid)
{
    if(shmctl(shmid,IPC_RMID,nullptr)==-1)
    {
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        exit(1);
    }
}

#endif

server.cc
#include "comm.hpp"

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

    sleep(5);

    char* start = (char*)attchShm(shmid);
    printf("attach success, adress start: %p\n",start);

    //使用
    while(true)
    {
        shmid_ds ds;
        shmctl(shmid,IPC_STAT,&ds);
        printf("获取信息: size:%d ,pid: %d ,myself: %d",ds.shm_segsz,ds.shm_cpid,getpid());
        printf("client say:%s\n",start);
        sleep(1);
    }

    //去关联
    detachShm(start);

    //删除
    deleteShm(shmid);
    return 0;
}

client
#include "comm.hpp"

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

    sleep(5);
    char* start = (char*)attchShm(shmid);

    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,mess
    }
    

    detachShm(start);
    return 0;
}

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

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

相关文章

React基础学习(一)

一、虚拟DOM和真实DOM <script type"text/babel"> // 此处一定要写babel!!!!!!!// 1. 创建虚拟DOM// const VDOM <h1 id"title">Hello, React!</h1> // 此处一定不要写引号 因为这不是字符串!!!!!!!const VDOM ( // 如果有多层嵌套&a…

PostgreSQL15.2最新版本安装_远程连接_Navicat操作_pgAdmin操作_Windows10上安装---PostgreSQL工作笔记001

首先去下载postgresql https://www.enterprisedb.com/downloads/postgres-postgresql-downloads 下载地址: 去上面的地址下载,最好下载10版本的,我这里下载的是15版本的,有问题,后面说吧 下载以后 然后双击安装 next 选择目录next next 输入密码next

好程序员:Java线下培训有必要吗?零基础想学Java怎么学?

有粉丝问好程序员&#xff1a;自己只有周末有时间&#xff0c;想报班学习Java编程&#xff0c;是线上学编程好还是线下学编程好&#xff1f;小源从实际客观以及学习效果的角度来讲&#xff0c;毫无疑问是线下学编程的效果会更好。为什么这样说呢&#xff1f; 比如&#xff1a;家…

初探强化学习

1.引言 人生中充满选择&#xff0c;每次选择就是一次决策&#xff0c;我们正是从一次次决策中&#xff0c;把自己带领到人生的下一段旅程中。在回忆往事的时候&#xff0c;我们会对生命中某些时刻的决策印象深刻&#xff1a;“还好当时选择了读研&#xff0c;毕业后找到了一份自…

学习小程序基础内容之逻辑交互

我们先来看一下实现的效果。 然后再来分享结构。 结构分为左右3:7 分配&#xff0c; 左侧是类别&#xff0c;右侧是该类别对应的品牌。 后台会在onload的请求把左侧的类别返回来&#xff0c;然后我们通过循环把数据展示出来。然后通过点击事件&#xff0c;把对应的品牌请求回来…

2023年,初级测试到高级测试开发工程师需要什么技能?卷起来......

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…

泵站水闸自动化系统调试方案

1、调试方案概述 调试方案分为自控系统现场调试、视频系统现场调试以及控制中心远程调试&#xff08;包含通讯测试、自控调试和视频调试&#xff09;。 自控系统现场调试分为触摸屏调试和本地上位机调试两部分。触摸屏系统的调试步骤如下&#xff1a; 确认触摸屏和PLC的通讯情…

C++标准库 -- 泛型算法 (Primer C++ 第五版 · 阅读笔记)

C标准库 -- 泛型算法 (Primer C 第五版 阅读笔记&#xff09; 第10章 泛型算法------(持续更新)10.1、概述10.2、初识泛型算法10.2.1、只读算法10.2.2、写容器元素的算法10.2.3、重排容器元素的算法 10.3、定制操作10.4、再探迭代器10.5、泛型算法结构10.6、特定容器算法 第10…

【ubuntu】将硬盘挂载到指定目录并设置开机自动挂载

最近打算将数据盘开机自动挂载&#xff0c;省得每次都要手动挂载&#xff0c;总结步骤如下&#xff1a; 输入以下命令&#xff0c;将系统中所有的分区都列出来&#xff1a; sudo fdisk -l找到你要挂载的分区&#xff0c;可以通过容量大小分辨&#xff0c;当然&#xff0c;有可…

黑马Mysql从入门到高级

文章目录 1. 数据库基础1.1 基础概念1.2 SQL1.2.1 语法1.2.2 数据类型1.2.3 DDL&#xff08;definition&#xff09; 1.3 函数1.3.1 字符串函数1.3.2 日期函数1.3.3 数字函数1.3.4 流程函数 1.4 约束1.5 多表查询1.5.1 连接1.5.2 联合查询 2. 数据库进阶2.1 存储引擎2.1.1 Inno…

中国人民大学与加拿大女王大学金融硕士——学习的阶段让未来的人生更丰盈

初入职场的新人拥有同样的起跑线&#xff0c;经过时间的沉淀&#xff0c;每个人之间就会有差距。差距是怎样被拉开的呢&#xff1f;也可以说是行动导致的。毕竟想是问题&#xff0c;去做才是答案&#xff0c;有行动才会有结果。在职读研与其停留在想的阶段&#xff0c;不如去准…

我发现了PMP通关密码!这14页纸直接背!

一周就能背完的PMP考试技巧只有14页纸 共分成了4大模块 完全不用担心看不懂 01关键词篇 第1章引论 1.看到“驱动变革”--选项中找“将来状态” 2.看到“依赖关系”--选项中找“项目集管理” 3.看到“价值最大化”--选项中找“项目组合管理” 4.看到“可行性研究”--选项中…

「线性DP-步入」最长上升子序列(LIS)

题目描述 给定一个长度为 N 的数列&#xff0c;求数值严格单调递增的子序列的长度最长是多少。 输入格式 第一行包含整数 N。 第二行包含 N 个整数&#xff0c;表示完整序列。 输出格式 输出一个整数&#xff0c;表示最大长度。 数据范围 1 ≤ N ≤ 1000 1≤N≤1000 1≤…

【进阶C语言】有关动态内存管理的经典笔试题(详细图文讲解)

前言 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff0c;喜爱音乐的一位博主。 &#x1f4d7;本文收录于C语言进阶系列&#xff0c;本专栏主要内容为数据的存储、指针的进阶、字符串和内存函数…

.class文件在线转成.java文件方法

使用背景&#xff1a; 工作中碰到老的项目就头疼&#xff0c;有些连源码都没有&#xff0c;解决bug只能从class文件反编译成java后&#xff0c;来读懂业务逻辑。 后来在网上找了一些工具来帮助class文件转码&#xff0c;有些遇到lamda表达式就转换错误&#xff0c;有些使用起…

正则表达式的字符串取反常用正则表达式

正则表达式的字符串取反操作 文件同步时&#xff0c;想要过滤掉扩展名为.tmp或者.TMP的临时文件&#xff0c;想要使用正则表达式对字符串进行取反操作。 注意&#xff1a;[^tmp]* 这种取反的表达式&#xff0c;只能表示匹配除了t、m、p以外的所有字符&#xff0c;是单字符匹配…

gRPC-Go源码解读三 服务端处理流程分析

相较于Client端的复杂处理流程&#xff0c;Server端相对来说简单了很多&#xff0c;核心就是创建个TCP套接字并监听&#xff0c;收到客户端连接请求则起个go协程处理&#xff0c;子协程根据请求中的服务名和方法名调用对应的服务方法处理&#xff0c;处理完成之后则返回响应。整…

叫板IT部门和专业软件公司,低代码成为企业数字化的新选择

从2017年政府将“数字经济”写入工作报告&#xff0c;到今年两会将企业数字化转型列为重点议题&#xff0c;数字化的口号已喊了6年。政策对于数字化的支持越来越坚定&#xff0c;令人欣喜的是&#xff0c;越来越多具有远见卓识的企业已将数字化建设作为工作重心。 然而&#xf…

【LeetCode】剑指 Offer 60. n个骰子的点数 p294 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/nge-tou-zi-de-dian-shu-lcof/ 1. 题目介绍&#xff08;60. n个骰子的点数&#xff09; 把n个骰子扔在地上&#xff0c;所有骰子朝上一面的点数之和为 s。输入 n&#xff0c;打印出 s 的所有可能的值出现的概率。 你需要用一…

Vue.js条件渲染指令v-if及v-show

目录 一、v-if 二、v-show 三、v-if与v-show的选择 一、v-if v-if是Vue.js的条件语句&#xff0c;v-if指令用于条件性地渲染一块内容&#xff0c;这块内容只会在指令的表达式返回true的时候被渲染。需要特别注意的是&#xff0c;v-if所关联的是Vue.js的动态变量。 v-if的使用…