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

news/2024/10/21 7:33:39/

Linux基础内容(19)—— 进程间通信(介绍与管道内容)_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/130034918?spm=1001.2014.3001.5502

目录

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 4096key_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);}
}#endifserver.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.ppmy.cn/news/48346.html

相关文章

第七章节 spring AOP

《Spring》篇章整体栏目 ————————————————————————————— 【第一章】spring 概念与体系结构 【第二章】spring IoC 的工作原理 【第三章】spring IOC与Bean环境搭建与应用 【第四章】spring bean定义 【第五章】Spring 集合注入、作用域 【第六章】…

什么是计算量flops,什么是参数量params?

flops与params 计算量对应我们之前的时间复杂度&#xff0c;参数量对应于我们之前的空间复杂度&#xff0c;这么说就很明显了 也就是计算量要看网络执行时间的长短&#xff0c;参数量要看占用显存的量 其中最重要的衡量CNN 模型所需的计算力就是flops&#xff1a; FLOPS&…

显存不够用?一种大模型加载时节约一半显存的方法

Loading huge PyTorch models with linear memory consumption 本文主要介绍了一种用于加载巨大模型权重时节约接近一半显存的方法 首先&#xff0c;创建一个模型: import torch from torch import nnclass BoringModel(nn.Sequential):def __init__(self):super().__init__…

【Leetcode -剑指Offer 22.链表中倒数第k个结点 -203.移除链表元素】

Leetcode Leetcode -剑指Offer 22.链表中倒数第k个结点Leetcode -203.移除链表元素 Leetcode -剑指Offer 22.链表中倒数第k个结点 题目&#xff1a;输入一个链表&#xff0c;输出该链表中倒数第k个节点。为了符合大多数人的习惯&#xff0c;本题从1开始计数&#xff0c;即链表…

OSCP-Clyde(rabbitmq中间件、erlang服务4369、修改Payload、nmap提权)

目录 扫描 FTP erlang服务(4369) 提权 扫描 21/tcp open ftp vsftpd 3.0.3 | ftp-anon: Anonymous FTP login allowed (FTP code 230) | drwxr-xr-x 2 ftp ftp 4096 Apr 24 2020 PackageKit | drwxr-xr-x 5 ftp ftp 4096 Apr 24 2020 apache2 | drwxr-xr-x 5 ftp ftp 409…

云原生之在kubernetes集群下部署Mysql应用

云原生之在kubernetes集群下部署mysql应用 一、Mysql介绍二、kubernetes集群介绍1.k8s简介2.k8s架构图 三、本次实践介绍1.本次实践简介2.本次环境规划 三、检查本地k8s集群环境1.检查k8s各节点状态2.检查k8s版本3.检查k8s系统pod状态 四、编辑mysql.yaml文件五、创建mysql应用…

Redis分布式锁有哪些缺点?如何解决?

目录 一、死锁问题&#xff1a; 二、锁竞争问题&#xff1a; 三、时效性问题&#xff1a; 四、单点故障问题&#xff1a; 五、高并发量下锁抢占时间长的问题 一、死锁问题&#xff1a; 因为每个客户端在设置锁过期时间时可能出现网络延迟等原因&#xff0c;有可能出现某个…

五项热门技术领域和应用场景

介绍五种当下比较热门的技术&#xff0c;分别是人工智能、云计算、数据分析、微服务和区块链。每种技术都有自己的定义、子领域、应用场景和学习难度。这些技术都有着广阔的发展前景和市场需求&#xff0c;对于想要从事或了解这些领域的人来说&#xff0c;都是很有价值的知识。…