共享内存(与消息队列相似)

news2025/4/18 18:45:25

目录

共享内存概述

共享内存函数 

 (1)shmget函数

功能概述

函数原型

参数解释

返回值

示例

结果

 (2)shmat函数

功能概述

函数原型

参数解释

返回值

 (3)shmdt函数

功能概述

函数原型

参数解释

返回值

示例1(所有函数结合总示例)

结果

示例2(内存偏移存取数据)

结果


共享内存概述

共享内存在进程间传输数据的效率极高。

概念:在物理内存中开辟一块区域,让多个进程能将其映射到各自虚拟地址空间,实现对同一块内存的共享访问。

原理:先由进程创建共享内存获标识符,其他进程再将其映射到自身地址空间,然后进程就能像访问普通内存一样对其进行读写操作。

优点:数据传输快,因为无需像其他通信方式那样进行数据复制;能支持大量数据传输,适合对大块数据的频繁访问。

缺点:需进程自行处理同步和互斥问题,以避免数据冲突;使用不当易引发程序错误和内存泄漏,且不支持跨机器的进程通信。

应用场景:常用于对通信速度要求高的场景,如实时数据处理系统、数据库系统中的缓冲区管理等。

共享内存函数 

 (1)shmget函数

功能概述

        shmget 是一个用于创建或获取共享内存段的系统调用,主要用于在类 Unix 系统(如 Linux)中实现进程间通信(IPC)

函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);
参数解释

        key:用于标识共享内存段的键值。它可以是通过 ftok 函数生成的唯一键值,也可以是 IPC_PRIVATE。若为 IPC_PRIVATE,则会创建一个新的、私有的共享内存段,该共享内存段只能由创建它的进程及其子进程访问。

        size:指定要创建或获取的共享内存段的大小,以字节为单位。若要创建新的共享内存段,此参数必须大于 0。

        shmflg:一组标志位,用于控制共享内存段的创建和访问权限。常见标志如下:

      IPC_CREAT:若指定的共享内存段不存在,则创建它。

      IPC_EXCL:与 IPC_CREAT 一起使用时,若共享内存段已存在,函数会失败并返回 -1。权限标志:如 0666,用于设置共享内存段的访问权限,类似于文件的权限设置。

返回值

        若调用成功,返回一个非负整数,即共享内存段的标识符(shmid),后续的共享内存操作会使用这个标识符。

        若失败,返回 -1,并设置 errno 来指示错误类型。

示例
#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

using namespace std;

typedef struct student
{
	char stuid[20];
	char stuname[20];
}STU;

int main()
{
	int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT | 0777);
	if (shmid < 0)
	{
		perror("shmget error");
	}

	return 0;
}
结果

下面第二个就是我们创建的共享内存

 (2)shmat函数

功能概述

        shmat 函数是类 Unix 系统(如 Linux)中用于将共享内存段附加到调用进程的地址空间的系统调用,通过它进程可以像访问自身内存一样访问共享内存段。

函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);
参数解释

        shmid:这是由 shmget 函数返回的共享内存段标识符,用于指定要附加的共享内存段。

        shmaddr:它指定共享内存段要附加到的进程地址空间的地址。一般可设置为 NULL,让系统自动选择合适的地址进行附加。

        shmflg:这是一组标志位,用于控制附加操作的行为,常见标志如下:

                SHM_RDONLY:以只读模式附加共享内存段,即进程只能读取共享内存中的数据,不能进行写入操作。

                0:以读写模式附加共享内存段。

返回值

        若调用成功,返回指向共享内存段在进程地址空间中起始地址的指针,后续进程可通过该指针访问共享内存段。

        若失败,返回 (void *)-1,并设置 errno 来指示错误类型。

 (3)shmdt函数

功能概述

        shmdt 函数在类 Unix 系统里用于将共享内存段从调用进程的地址空间分离。分离后,进程就无法再通过之前附加时得到的指针来访问该共享内存段,但共享内存段本身并不会被删除,其他仍附加了该共享内存段的进程依旧可以访问它。

函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int shmdt(const void *shmaddr);
参数解释

        shmaddr:这是一个指向共享内存段在进程地址空间中起始地址的指针,该指针是之前调用 shmat 函数时返回的。

返回值

        若调用成功,返回 0

        若失败,返回 -1,同时设置 errno 以指示错误类型。

示例1(所有函数结合总示例)

Amain.cpp发送数据

#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>

using namespace std;

typedef struct student
{
	char stuid[20];
	char stuname[20];
}STU;

int main()
{
	void* shmaddr = NULL;
	int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT | 0777);
	if (shmid < 0)
	{
		perror("shmget error");
	}
	else
	{
		// 链接共享内存
		shmaddr = shmat(shmid, NULL, 0);

		// 共享内存写入数据
		STU stu = { "2019211001", "zhangsan" };
		memcpy(shmaddr, &stu, sizeof(STU));

		// 断开链接共享内存
		shmdt(shmaddr);
	}

	return 0;
}

Bmain.cpp接收数据

#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>

using namespace std;

typedef struct student
{
	char stuid[20];
	char stuname[20];
}STU;

int main()
{
	void* shmaddr = NULL;
	int shmid = shmget((key_t)1002, sizeof(STU), IPC_CREAT | 0777);
	if (shmid < 0)
	{
		perror("shmget error");
	}
	else
	{
		// 链接共享内存
		shmaddr = shmat(shmid, NULL, 0);

		// 共享内存取数据
		STU stu = { 0 };
		memcpy(&stu, shmaddr, sizeof(STU));

		cout << "学号:" << stu.stuid << endl;
		cout << "姓名:" << stu.stuname << endl;

		memset(shmaddr, 0, sizeof(STU)); // 清空共享内存数据

		// 断开链接共享内存
		shmdt(shmaddr);
	}

	return 0;
}

注:因为是对内存直接操作,所以在取完数据之后记得清空内存 

结果

示例2(内存偏移存取数据)

Amain.cpp

#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>

using namespace std;

typedef struct student
{
	char stuid[20];
	char stuname[20];
}STU;

int main()
{
	void* shmaddr = NULL;
	int shmid = shmget((key_t)1002, sizeof(STU)*3, IPC_CREAT | 0777);
	if (shmid < 0)
	{
		perror("shmget error");
	}
	else
	{
		// 链接共享内存
		shmaddr = shmat(shmid, NULL, 0);

		// 共享内存写入数据
		STU stu = { 0 };

		for (int i = 1; i < 4; i++)
		{
			sprintf(stu.stuid, "%d", i);
			sprintf(stu.stuname, "name%d", i);

			memcpy(shmaddr + sizeof(STU) * (i - 1), &stu, sizeof(STU));
		}

		// 断开链接共享内存
		shmdt(shmaddr);
	}

	return 0;
}

 Bmain.cpp

#include <iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>

using namespace std;

typedef struct student
{
	char stuid[20];
	char stuname[20];
}STU;

int main()
{
	void* shmaddr = NULL;
	int shmid = shmget((key_t)1002, sizeof(STU)*3, IPC_CREAT | 0777);
	if (shmid < 0)
	{
		perror("shmget error");
	}
	else
	{
		// 链接共享内存
		shmaddr = shmat(shmid, NULL, 0);

		// 共享内存取数据
		STU stu = { 0 };
		
		for (int i = 1; i < 4; i++)
		{
			memcpy(&stu, shmaddr + sizeof(STU) * (i - 1), sizeof(STU));

			cout << "次数" << i << "学号:" << stu.stuid << endl;
			cout << "次数" << i << "姓名:" << stu.stuname << endl;
		}

		memset(shmaddr, 0, sizeof(STU)); // 清空共享内存数据

		// 断开链接共享内存
		shmdt(shmaddr);
	}

	return 0;
}
结果

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

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

相关文章

2025年常见渗透测试面试题- PHP考察(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 PHP考察 php的LFI&#xff0c;本地包含漏洞原理是什么&#xff1f;写一段带有漏洞的代码。手工的话如何发掘&am…

【C++进阶】关联容器:multimap类型

目录 一、multimap 基础概念与底层实现 1.1 定义与核心特性 1.2 底层数据结构 1.3 类模板定义 1.4 与其他容器的对比 二、multimap 核心操作详解 2.1 定义与初始化 2.2 插入元素 2.3 查找元素 2.4 删除元素 2.5 遍历元素 三、性能分析与适用场景 3.1 时间复杂度分…

远程管理命令:关机和重启

关机/重启 序号命令对应英文作用01shutdown 选项 时间shutdown关机 / 重新启动 一、shutdown shutdown 命令可以安全关闭 或者 重新启动系统。 选项含义-r重新启动 提示&#xff1a; 不指定选项和参数&#xff0c;默认表示 1 分钟之后 关闭电脑远程维护服务器时&#xff0…

【MySQL】001.MySQL安装

文章目录 一. MySQL在Ubuntu 20.04 环境安装1.1 更新软件包列表1.2 安装MySQL服务器1.3 配置安全设置1.4 检查mysql server是否正在运行1.5 进行连接1.6 查询自带的数据库 二. 配置文件的修改三. MySQL连接TCP/IP时的登陆问题四. MySQL中的命令 一. MySQL在Ubuntu 20.04 环境安…

vue 入门:组件事件

文章目录 vue介绍vue 入门简单示例自定义组件事件 vue介绍 vue2 官网 Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层。 vue 入门 Vue.js 的核心是一个允许采用简洁的模板语…

数据质量问题中,数据及时性怎么保证?如何有深度体系化回答!

数据治理&#xff0c;数据质量这快是中大厂&#xff0c;高阶大数据开发面试必备技能&#xff0c;企业基于大数据底座去做数仓&#xff0c;那么首先需要保障的就是数据质量。 数据质量的重要性在现代企业中变得越发突出。以下是数据质量的几个关键方面&#xff0c;说明其对企业…

数据可视化 —— 折线图应用(大全)

一、导入需要的库 # Matplotlib 是 Python 最常用的绘图库&#xff0c;pyplot 提供了类似 MATLAB 的绘图接口 import matplotlib.pyplot as plt import numpy as np import pandas as pd 二、常用的库函数 plt.plot(x轴,y轴)&#xff1a;plot()是画折线图的函数。 plt.xlabe…

什么是中性线、零线、地线,三相四线制如何入户用电

在变压器三相电侧&#xff0c;按照星形连接法&#xff0c;有一个中心点&#xff0c;这根线引出来的线接不接地&#xff1a;不接地就是中性线&#xff0c;接地就是零线 下面就是没有接地&#xff1a;中性线 接地了以后就可以叫做零线了 三相电在高压输电的时候是没有零线的&a…

【含文档+PPT+源码】基于Android家政服务系统的开发与实现

介绍视频&#xff1a; 课程简介&#xff1a; 本课程演示的是一款基于Android家政服务系统的开发与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.…

配置mac mini M4 的一些软件

最近更换了 mac mini M4 &#xff0c;想要重新下载配置软件 &#xff0c;记录一下。 Homebrew是什么&#xff1f; homebrew是一款Mac OS平台下的软件包管理工具&#xff0c;拥有安装、卸载、更新、查看、搜索等功能。通过简单的指令可以实现包管理&#xff0c;而不用关心各种…

Java——抽象方法抽象类 接口 详解及综合案例

1.抽象方法抽象类 介绍 抽象方法: 将共性的行为(方法)抽取到父类之后&#xff0c; 由于每一个子类执行的内容是不一样&#xff0c; 所以&#xff0c;在父类中不能确定具体的方法体。 该方法就可以定义为抽象方法。 抽象类: 如果一个类中存在抽象方法&#xff0c;那么该类就必须…

【计网】一二章习题

1. (单选题, 3 分) 假设主机A和B之间的链路带宽为100Mbps&#xff0c;主机A的网卡速率为1Gbps&#xff0c;主机B的网卡速率为10Mbps&#xff0c;主机A给主机B发送数据的最高理论速率为&#xff08; &#xff09;。 A. 100Mbps B. 1Gbps C. 1Mbps D. 10Mbps 正确答案 D 发…

【软考-高级】【信息系统项目管理师】【论文基础】进度管理过程输入输出及工具技术的使用方法

定义 项目进度管理是为了保证项目按时完成&#xff0c;对项目中所需的各个过程进行管理的过程&#xff0c;包括规划进度、定义活动、活动优先级排序、活动持续时间、制定进度计划和控制进度。 管理基础 制定进度计划的一般步骤 选择进度计划方法&#xff08;如关键路径法&a…

TOGAF之架构标准规范-技术架构

TOGAF是工业级的企业架构标准规范&#xff0c;本文主要描述技术架构阶段。 如上所示&#xff0c;技术架构&#xff08;Technology Architecture&#xff09;在TOGAF标准规范中处于D阶段 技术架构阶段 技术架构阶段的主要内容包括阶段目标、阶段输入、流程步骤、阶段输出、架构…

Ansys Electronics 变压器 ACT

你好&#xff0c; 在本博客中&#xff0c;我将讨论如何使用 Ansys 电子变压器 ACT 自动快速地设计电力电子电感器或变压器。我将逐步介绍设计和创建电力电子变压器示例的步骤&#xff0c;该变压器为同心组件&#xff0c;双绕组&#xff0c;采用正弦电压激励&#xff0c;并应用…

十三种物联网/通信模块综合对比——《数据手册--物联网/通信模块》

物联网&#xff0f;通信模块 名称 功能 应用场景 USB转换模块 用于将USB接口转换为其他类型的接口&#xff0c;如串口、并口等&#xff0c;实现不同设备之间的通信。 常用于计算机与外部设备&#xff08;如打印机、扫描仪等&#xff09;的连接&#xff0c;以及数据传输和设…

Redis安装(Windows环境)

文章目录 Resid简介:下载Redis启动Redis服务设置Windows服务常用的Redis服务命令 Resid简介: Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库&#xff0c;并提供多种语言的 API。 Redis通常…

FreeRTOS项目工程完善指南:STM32F103C8T6系列

FreeRTOS项目工程完善指南&#xff1a;STM32系列 本文是FreeRTOS STM32开发系列教程的一部分。我们将完善之前移植的FreeRTOS工程&#xff0c;添加串口功能并优化配置文件。 更多优质资源&#xff0c;请访问我的GitHub仓库&#xff1a;https://github.com/Despacito0o/FreeRTO…

论坛系统(测试报告)

文章目录 一、项目介绍二、设计测试用例三、自动化测试用例的部分展示用户名或密码错误登录成功编辑自己的帖子成功修改个人信息成功回复帖子信息成功 四、性能测试总结 一、项目介绍 本平台是用Java开发&#xff0c;基于SpringBoot、SpringMVC、MyBatis框架搭建的小型论坛系统…

【汽车产品开发项目管理——端到端的汽车产品诞生流程】

MPU&#xff1a;集成运算器、寄存器和控制器的中央处理器芯片 MCU&#xff1a;微控制单元&#xff0c;将中央处理器CPU、存储器ROM/RAM、计数器、IO接口及多种外设模块集成在单一芯片上的微型计算机系统。 汽车产品开发项目属性&#xff1a;临时性、独特性、渐进明细性、以目标…