进程间通信之共享内存

news2025/1/10 11:23:21

共享内存

  • 一. 什么是共享内存
  • 二. 共享内存有关函数
    • 1.获取key
    • 2.打开创建共享内存对象 - shmget
    • 3.映射空间地址 - shmat
    • 4.取消映射 - shmdt
    • 5.删除共享内存对象 - shmctl
  • 三. 实例
  • 四. 注意事项
    • 1.查看当前系统的共享内存
    • 2.当两个进程间ftok参数不一样时,shmid也不一样,共享内存不是同一个空间
    • 3.释放共享内存

一. 什么是共享内存

共享内存就是允许两个或多个进程共享一片存储区,是操作系统在实际物理内存开辟一块空间,当一个进程往该空间写入内容时,另外一进程会访问该空间,得到写入的值,即实现了进程间的通信。
共享内存做到数据不需要在客户机和服务器端之间来回复制,数据直接写到内存中,不需要多次数据拷贝,是进程间最有效的方式
在这里插入图片描述

二. 共享内存有关函数

1.获取key

功能 : 获取一个独一无二的key,作为传给共享内存的一个参数

#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);
key_t key = ftok("./read", 'a');
pathname:
		提前创建的可访问文件的文件名,可以随意写
proj_id:
		任意一个字符

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

2.打开创建共享内存对象 - shmget

功能:创建/打开一个共享内存对象

#include <sys/ipc.h>
#include <sys/shm.h>

//在内核上创建共享内存
int shemid = shmget(key, 1024, IPC_CREAT | 0666);
int shmget(key_t key, size_t size, int shmflg);

key:
		表示要打开或者创建一个对象的“密钥”
		可以写0或者IPC_PRIVATE:表示共享内存对象是私有的
size:
		要创建的共享内存大小
shmflg:
		打开或者创建时的权限
		IPC_CREAT:不存在则创建
		IPC_EXCL:存在(如果加上了IPC_CREAT)就报错
		0666
返回值:
		成功返回ID号,失败返回-1

3.映射空间地址 - shmat

功能:把内核中的共享内存空间映射到用户空间

#include <sys/types.h>
#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);
char *shmaddr = shmat(shmid, NULL, 0);
void *shmat(int shmid, const void *shmaddr, int shmflg);

shmid:
		共享内存的id号
shmaddr:
		可以指定要映射的空间地址
		NULL:表示系统决定
		0x...:表示指定要把内核空间映射到这个地址
shmflg:
		表示共享内存的操作权限(读写)
		SHM_RDONLY:表示只读(不用)
		0:可读可写
返回值:
		成功返回映射后的用户空间地址,失败返回(void *)-1

4.取消映射 - shmdt

功能:把shmat映射后的空间取消掉,释放进程地址空间

#include <sys/types.h>
#include <sys/shm.h>

int shmdt(const void *shmaddr);
shmaddr:
		shmat返回的地址(映射地址)
返回值:
		成功返回0,失败返回-1

5.删除共享内存对象 - shmctl

功能:整体控制共享内存对象

#include <sys/ipc.h>
#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

shmctl(shmid, IPC_RMID, NULL);
shmid:
		共享内存对象ID号
cmd:
		要执行的操作
		IPC_STAT  (获取对象属性)
    	IPC_SET (设置对象属性)
    	IPC_RMID (删除对象)
buf:
		用于设置或者获取对象的属性,如果是删除对象,写NULL
返回值:
		成功返回0,失败返回-1

注:删除对象并不是直接删除,而是标记这个对象为删除状态

三. 实例

write.c依次往共享内存中输入字符a-z, read.c读取共享内存中的数据,并打印出来
write.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>


int main()
{
    key_t key = ftok("./read", 'a');
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }

    // 创建共享内存
    int shmid = shmget(key, 1024*4, IPC_CREAT | 0666);
    if(shmid < 0)
    {
        perror("shmget");
        return -1;
    }

    // 映射空间地址
    char *shmaddr = shmat(shmid, NULL, 0);
    if(shmaddr == (void *)-1)
    {
        perror("shmat");
        return -1;
    }

    char c='a';
    for( ; c <= 'z'; c++)
    {
        printf("%c\n",c);
        shmaddr[c-'a']=c;
        sleep(1);
    }
    shmdt(shmaddr);
    shmctl(shmid, IPC_RMID, NULL);
}

read.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>


int main()
{
    key_t key = ftok("./read", 'a');
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }

    //在内核上创建共享内存
    int shmid = shmget(key, 1024*4,IPC_CREAT|0666);
    if(shmid < 0)
    {
        perror("shmget");
        return -1;
    }

    //映射空间地址
    char *shmaddr = shmat(shmid, NULL, 0);
    if(shmaddr == (void *)-1)
    {
        perror("shmat");
        return -1;
    }

    int i = 20;
    while(i)
    {	
        printf("result : %s\n", shmaddr);
        sleep(1);
        i--;
    }
    shmdt(shmaddr);
    shmctl(shmid, IPC_RMID, NULL);

}

在这里插入图片描述

注意 : 当运行程序时,先运行read.c,程序启动就直接读取共享内存中的数据,此时并没有往共享内存中写入数据,
但是read.c并没有阻塞

四. 注意事项

1.查看当前系统的共享内存

	ipcs -m    			//查看当前系统的共享内存
	ipcs -m shmid       //删除某个共享内存

在这里插入图片描述

2.当两个进程间ftok参数不一样时,shmid也不一样,共享内存不是同一个空间

write.c
在这里插入图片描述

read.c
在这里插入图片描述
在这里插入图片描述

3.释放共享内存

当我结束两个进程时,如果代码中没有shmctl,那么共享内存还会一直存在,会造成内存泄漏,所以当我们使用shmget创建共享内存后,如果不在使用该共享内存,应当即时释放

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

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

相关文章

第04章_IDEA的安装与使用(下)

第04章_IDEA的安装与使用&#xff08;下&#xff09; 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 8. 快捷键的使用 8.1 常用快捷键 见《尚硅谷_宋红康_IntelliJ IDEA 常用快捷键一览表.md》…

【机器视觉1】光源介绍与选择

文章目录一、常见照明光源类型二、照明光源对比三、照明技术3.1 亮视野与暗视野3.2 低角度照明3.3 前向光直射照明3.4 前向光漫射照明3.5 背光照明-测量系统的最佳选择3.6 颜色与补色示例3.7 偏光技术应用四、镜头4.1 镜头的几个概念4.2 影响图像质量的关键因素4.3 成像尺寸4.4…

迁移Visual Studio2022到非系统盘

参考&#xff1a;VS2019/VS2022移动安装位置CSDN博客 已经安装VS Studio2022&#xff0c;默认在了C盘&#xff0c;下面是VS2022更换安装位置的方法&#xff1a;将安装好的文件剪切到其他盘&#xff0c;然后mklink链接。 第一步&#xff1a;将安装好的文件剪切到其他盘 以下为…

C++ 实现 matlab 的 buttord函数

文章目录1. matlab 的 buttord函数 的作用2. matlab 的 buttord函数 的使用方法3. C 实现代码4. 测试代码和结果4.1 定义滤波器的设计指标的结构体4.2 C 测试文件4.3 测试结果1. matlab 的 buttord函数 的作用 根据给定的巴特沃斯滤波器的指标计算滤波器的最低阶数和截止频率 …

【蓝桥杯嵌入式】蓝桥杯嵌入式第十四届省赛程序真题,真题分析与代码讲解

&#x1f38a;【蓝桥杯嵌入式】专题正在持续更新中&#xff0c;原理图解析✨&#xff0c;各模块分析✨以及历年真题讲解✨都已更新完毕&#xff0c;欢迎大家前往订阅本专题&#x1f38f; &#x1f38f;【蓝桥杯嵌入式】蓝桥杯第十届省赛真题 &#x1f38f;【蓝桥杯嵌入式】蓝桥…

k8s ingress controller 使用

目录 一 安装Ingress controller 二 创建service deploy 三 创建ingress 四 测试 一 安装Ingress controller apiVersion: v1 kind: Namespace metadata:name: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/instance: ingress-nginx--- # …

怎么把wav转换成mp3格式,5种方法值得收藏

怎么把wav转换成mp3格式&#xff1f;wav格式相信很多小伙伴们不是很熟悉&#xff0c;这种文件格式通常用于录音室等一些专业音乐项目上&#xff0c;那么wav格式和mp3格式有什么区别呢&#xff1f;wav全名Waveform Audio File Format&#xff0c;是微软公司开发的一种声音文件格…

【HarmonyOS】小熊派鸿蒙系统搭建

文章目录一、BearPi-HM Micro 开发板介绍二、Linux镜像下载三、BearPi-HM Micro编译环境配置1.首先添加如下镜像源2.更新镜像源3.安装依赖库及工具4.安装hb5.测试hb是否安装成功四、安装mkimage工具1.新建tools目录2.下载mkimage.stm32工具到~/tools目录&#xff0c;并复制到/h…

谷粒商城-分布式基础篇3

1.商品服务-品牌管理 把逆向生成的前端代码复制到前端src\views\modules\product 这样我们基本的增删改查就有了 全局搜索isAuth,修改返回值为true 关闭eslint build\webpack.base.conf.js const createLintingRule () > ({// test: /\.(js|vue)$/,// loader: eslint-lo…

真题详解(线性表)-软件设计(四十八)

原创 真题详解(UML图&#xff09;-软件设计&#xff08;四十七)https://blog.csdn.net/ke1ying/article/details/130096516 TCP 属于传输层&#xff0c; 用TCP连接的应用层有&#xff1a; SMTP&#xff08;25&#xff09; HTTP&#xff08;80&#xff09; Telnet&#xff08;…

kitti数据集中---标注数据label_2

标注文件中16个属性&#xff0c;即16列。但我们只能够看到前15列数据&#xff0c;因为第16列是针对测试场景下目标的置信度得分&#xff0c;也可以认为训练场景中得分全部为1但是没有专门标注出来。下图是000001.txt的标注内容和对应属性介绍。 相机坐标系中&#xff0c;y方向是…

【软考数据库】第一章 计算机系统基础知识

目录 1.1 计算机系统 1.1.1 计算机硬件组成 1.1.2 中央处理单元 1.1.3 数据表示 1.1.4 校验码 1.2 计算机体系结构 1.2.1 体系结构分类 1.2.2 指令系统存 1.2.3 储系系统 1.2.4 输入/输出技术 1.2.5 总线结构…

【Golang开发面经】字节跳动(三轮技术面)

一面 epoll、select、poll 区别 select 机制刚开始的时候&#xff0c;需要把 fd_set 从用户空间拷贝到内核空间&#xff0c;并且检测的 fd 数是有限制的&#xff0c;由 FD_SETSIZE 设置&#xff0c;一般是1024。数组实现。 poll 的实现和 select 非常相似&#xff0c;只是描…

Node【一】初识Node

文章目录&#x1f31f;前言&#x1f31f;Node.js&#x1f31f;特性&#xff1a;&#x1f31f;1. 单线程&#x1f31f;2.异步IO&#x1f31f;前端中的异步&#x1f31f;Node中的异步&#x1f31f;3.跨平台&#x1f31f;4.运行速度快&#x1f31f; 劣势&#xff1a;&#x1f31f;…

ASP一个物流商品运输系统的设计与实现

物流运输行业的今天正朝着追求高效、低成本、稳定可靠的方向发展。本文详细介绍了网上物流管理系统&#xff0c;涉及到客户端运输线路设计、过程跟踪等功能模块以及管理员端的相应模块的具体实现&#xff0c;分析了整个系统的架构、工作原理、实现功能等。系统采用ASPMS SQL以B…

代码随想录算法训练营第43天 | 动态规划 背包理论基础 LeetCode1049.最后一块石头的重量II,494.目标和,474.一和零

代码随想录算法训练营第43天 | 动态规划 背包理论基础 LeetCode1049.最后一块石头的重量II&#xff0c;494.目标和&#xff0c;474.一和零 1049.最后一块石头的重量II 第一遍读题思考 重点在于背包问题的理论基础建议阅读以下两个链接。 背包问题理论基础&#xff0c;用二维…

sed命令基础

sed编辑器即流编辑器&#xff08;stream editor&#xff09;&#xff0c;根据命令处理数据流中的数据&#xff0c;这些命令可从命令行输入&#xff0c;或者指定文件中输入。 sed执行的操作如下&#xff1a; 1&#xff09;从输入读取一行数据 2&#xff09;根据提供的命令匹配数…

KSS-ICP: 基于形状分析技术的点云配准方法

目录 1. 概述 2. 算法实现 3. 实验结果 总结 Reference 三维点云配准是三维视觉领域一个经典问题&#xff0c;涉及三维重建&#xff0c;定位&#xff0c;SLAM等具体应用问题。传统的配准可以被分为两条技术路线&#xff0c;即基于全局姿态匹配的方法以及基于特征点对应的方法。…

疫情下社区管理系统的设计与实现(论文+源码)_kaic

疫情下社区管理系统 摘 要&#xff1a;新冠疫情下的社区人员管理系统是基于SpringBoot搭建的一套前后端分离系统。面向疫情下的社区管理人员和社区用户&#xff0c;主要用于进行社区服务&#xff0c;进行高效的社区人员管理。具有一定的经济效益和社会效益。本文分析了新冠疫情…

计算机网络第三章(数据链路层)【湖科大教书匠】

1. 概述 物理层发出去的信号需要通过数据链路层才知道是否到达目的地&#xff1b;才知道比特流的分界线 链路(Link)&#xff1a;从一个结点到相邻结点的一段物理线路&#xff0c;中间没有任何其他交换结点数据链路(Data Link)&#xff1a;把实现通信协议的硬件和软件加到链路…