当前位置: 首页 > news >正文

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

目录

共享内存概述

共享内存函数 

 (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.dtcms.com/a/123155.html

相关文章:

  • 【Java面试系列】Spring Boot微服务架构下的分布式事务解决方案与性能优化详解 - 3-5年Java开发必备知识
  • Elasticsearch 系列专题 - 第五篇:集群与性能优化
  • P1359 洛谷 租用游艇
  • GPU NPU TPU的区别与联系
  • Jupyter notebook使用技巧
  • MIT6.S081 - Lab7 Multithreading(进程调度)
  • 玩转Docker | 使用Docker搭建Van-Nav导航站
  • KTH5772 系列游戏手柄摇杆专用3D 霍尔位置传感器
  • dify+wan2.1搭建文生视频生成工具流
  • 代码随想录-06-二叉树-05.05 N叉树的层序遍历
  • Mysql索引(四)
  • 光芯片一般性可靠性检测条目
  • 辉视客房控制系统:打造智慧酒店的六大核心价值
  • 【Linux】网络编程
  • 从质检到实验:Python三大T检验实战案例
  • 【Raqote】 1.3 路径填充ShaderClipBlendMaskBlitter结构体(blitter.rs)
  • Vue报错...properly without JavaScript enabled. Please enable it to continue
  • P1216 洛谷 数字三角形
  • 文件相关:echo重定向管道命令扩展详解
  • 论坛系统(测试报告)
  • 1.5SMC62A 单向瞬态抑制二极管,精准防护电路过压
  • 汽车软件开发常用的需求管理工具汇总
  • 校园食堂采购管理系统源码开发指南:探索数据大屏可视化建设
  • 微服务多模块构建feign项目过程与一些报错(2025详细版)
  • 【Java学习】如何利用AI学习Java语言开发(二)
  • linux shell编程规范与变量(一)
  • 25.4.10学习总结
  • 大数据Hadoop(MapReduce)
  • SQL 不走索引的常见情况
  • 小白电路设计-设计7-固定式倍压器直流稳压电源电路设计