Linux进程通信——共享内存

概念

共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。

特点

共享内存是最快的一种 IPC,因为进程是直接对内存进行存取
因为多个进程可以同时操作,所以需要进行同步
信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。

原理

创建

1、创建共享内存
2、进程A连接共享内存,写入数据(这里需要给进程A一个睡眠时间:两个进程同时操作需要同步,进程A写入数据后睡眠一定时间,在这个时间内进程B将数据读取,实现数据交换)
3、进程A断开连接
4、进程B连接共享内存,读取数据
5、进程B断开连接
6、释放公共内存

常用API

头文件

#include <sys/types.h>
#include <sys/shm.h>
//以下几个API都包含以上两个头文件

shmget函数

功能

创建或获取一个共享内存

函数原型

int shmget(key_t key, size_t size, int shmflg);

参数解读

keyftok生成的key标识,标识系统的唯一IPC资源
size需要申请共享内存的大小。在操作系统中,申请内存的最小单位为页,一页是4k字节,为了避免内存碎片,我们一般申请的内存大小为页的整数倍,即以兆为单位
shmflg如果要创建新的共享内存,需要使用IPC_CREAT,IPC_EXCL,后面需要加权限标志,权限标志与文件的读取操作一样。如果是已经存在的,可以使用IPC_CREAT或直接传0(只需获取而不用创建,yi)

返回值

成功时返回一个新建或已经存在的的共享内存标识符,取决于shmflg的参数。失败返回-1并设置错误码。

shmat函数

功能

第一次创建完共享内存时,它还不能被任何进程访问,shmat函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间,即将共享内存映射进进程中。

函数原型

void *shmat(int shm_id, const void *shm_addr, int shmflg); 

参数解读

shm_id由shmget函数返回的共享内存标识
*shm_addr指定共享内存连接到当前进程中的地址位置,通常为空(为0),表示让系统为我们安排共享内存的地址
shmflg

若指定了SHM RDONLY位,则以只读方式连接此段,否则以读写方式连接此段(输入0即可,表示映射进的共享内存可读可写

返回值

成功返回共享存段的指针(虚拟地址),并且内核将使其与该共享存段相关的shmid_ds(第四个函数的第三个参数)结构中的shm_nattch计数器加1 (类似于引用计数,即内存占用计入总内存) ; 出错返回-1

shmdt函数

功能

当一个进程不需要共享内存的时候,就需要去关联。该函数并不删除所指定的共享内存区,而是将之前用shmat函数连接好的共享内存区脱离目前的进程

函数原型

int shmdt(const void *shmaddr); 

参数解读

*shmaddr:是shmat函数返回的地址指针,只需将其返回值的函数变量名(代码地址)写入即可

返回值

调用成功时返回0,失败时返回-1。

shmctl函数

功能

控制共享内存

函数原型

int shmctl(int shm_id, int command, struct shmid_ds *buf);  

参数解读

shm_idshmget函数返回的共享内存标识符
commandcommand是要采取的操作,它可以取下面的三个值
IPC_STAT把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值
IPC_SET如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID(常用)删除共享内存段

*bufbuf是一个结构指针,它指向共享内存模式和访问权限的结构(不关心,一般写0

返回值

成功时返回0,失败返回-1并设置错误码。

代码示例

shmw.c

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

int main()
{
	key_t key;
	int shmid;
	char *shmaddr = NULL;	

	key = ftok(".",1);//当前目录建立IPC
	
	shmid = shmget(key,1024*4,IPC_CREAT|0666);//以可读可写方式开辟一个4兆大小的共享内存
	if(shmid == -1)
	{
		printf("create gxdl failed\n");
		exit(-1);
	}

	shmaddr = shmat(shmid,0,0);//将共享内存映射到进程中

	printf("connect success!\n");
	strcpy(shmaddr,"hello word!");
	
	sleep(5);//因为写入和读取是同步,所以此时执行完写入代码后需等待读取数据后一起关闭共享内存
	
	shmdt(shmaddr);//断开连接共享内存

	shmctl(shmid,IPC_RMID,0);//删除共享内存
	printf("over\n");

	return 0;
}

shmr.c

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

int main()
{
	key_t key;
	int shmid;
	char *shmaddr = NULL;	

	key = ftok(".",1);
	
	shmid = shmget(key,1024*4,0);//这里只需找到已经开辟的共享内存,所以参数为0即可
	if(shmid == -1)
	{
		printf("create gxdl failed\n");
		exit(-1);
	}

	shmaddr = shmat(shmid,0,0);//映射共享内存

	printf("connect success!\n");
	printf("content is %s\n",shmaddr);//将共享内存数据打印出来
	
	shmdt(shmaddr);//断开共享内存

	printf("over\n");

	return 0;
}

shmw.c程序运行,写入端往共享内存写入数据,并让其等待5s,这5s内shmr.c程序运行,读取端读取共享内存数据并将内容打印出来,5s后两者同时关闭共享内存输出over。

fork函数的补充

功能

系统IPC键值的格式转换函数,系统建立IPC通讯 (消息队列、信号量和共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。

函数原型

key_t ftok( const char * fname, int id );

参数解读

fname就是你指定的文件名(已经存在的文件名),一般使用当前目录
id子序号。虽然是int类型,但是只使用8bits(1-255)

例如

key_t key;
key = ftok(".", 1); //当前文件只需加.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

排序算法--归并排序

实现逻辑 ① 将序列每相邻两个数字进行归并操作&#xff0c;形成floor(n/2)个序列&#xff0c;排序后每个序列包含两个元素 ② 将上述序列再次归并&#xff0c;形成floor(n/4)个序列&#xff0c;每个序列包含四个元素 ③ 重复步骤②&#xff0c;直到所有元素排序完毕 void pri…

透视未来:现代发电厂地区可视化与智慧能源的结合

随着全球能源消费的不断增长&#xff0c;电力需求也在不断上升。作为能源行业的重要组成部分&#xff0c;现代发电厂扮演着不可替代的角色。而现代发电厂的数据管理和监控系统&#xff0c;则是确保其安全、高效、稳定运行的重要手段。在这个背景下&#xff0c;现代发电厂地区可…

全局定制序列化

作用:将返回实体类中的属性如果为null 变成"" package com.example.micrweb.config;import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.f…

windows搭建gitlab教程

1.安装gitlab 说明&#xff1a;由于公司都是windows服务器&#xff0c;这里安装以windows为例&#xff0c;先安装一个虚拟机&#xff0c;然后安装一个docker&#xff08;前提条件&#xff09; 1.1搜索镜像 docker search gitlab #搜索所有的docker search gitlab-ce-zh #搜索…

LabVIEW中将SMU信号连接到PXI背板触发线

LabVIEW中将SMU信号连接到PXI背板触发线 本文介绍如何将信号从PXI&#xff08;e&#xff09;SMU卡路由到PXI&#xff08;e&#xff09;机箱上的背板触发线。该过程涉及使用NI-DCPowerVI将SMU信号导出到PXI_TRIG线上。 在继续操作之前&#xff0c;请确保在开发PC上安装了兼容版…

安防视频EasyCVR平台太阳能供电+4G摄像头视频监控方案的建设

在工地、光伏、风电站、水库河道等场景中&#xff0c;以及一些偏远地区的项目现场&#xff0c;会存在无网无电情况&#xff0c;大大制约了视频监控系统建设的效率及可行性。在这种场景中&#xff0c;我们也可以通过太阳能供电4G监控摄像机的方案&#xff0c;满足偏远地区无网无…

VUE语法-$refs和ref属性的使用

1、$refs和ref属性的使用 1、$refs:一个包含 DOM 元素和组件实例的对象&#xff0c;通过模板引用注册。 2、ref实际上获取元素的DOM节点 3、如果需要在Vue中操作DOM我们可以通过ref和$refs这两个来实现 总结:$refs可以获取被ref属性修饰的元素的相关信息。 1.1、$refs和re…

IT 领域中的主要自动化趋势

48%的IT自动化流程属于IT服务管理&#xff0c;过去一年中&#xff0c;IT运维自动化增长了272%。 IT部门从交付者转变为战略伙伴 今年的《工作自动化指数》数据显示&#xff0c;自动化正在蔓延到组织的各个部门&#xff0c;越来越多的部门采用自动化&#xff0c;并且IT以外的员工…

oracle “ORA-25153:临时表空间为空”

从生产上面备份出来了一个数据库&#xff0c;应用在使用时显示ORA-25153临时表空间为空的报错&#xff0c;原因一般是数据库迁移时&#xff0c;没有迁移完整造成的 解决方法 1.创建新的临时表空间temp2 create temporary tablespace temp2 tempfile DATA size 100M autoexten…

【C语言】深入理解指针(四)

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 ✏️真正相信奇迹的家伙&#xff0c;本身和奇迹一样了不起啊&#xff01; 欢迎大家关注&#x1f50d;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;>希望看完我的文章对你有小小的帮助&am…

2023-11-22 LeetCode每日一题(网格中的最小路径代价)

2023-11-22每日一题 一、题目编号 2304. 网格中的最小路径代价二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始的整数矩阵 grid &#xff0c;矩阵大小为 m x n &#xff0c;由从 0 到 m * n - 1 的不同整数组成。你可以在此矩阵中&#xff0c;从一个…

常用通信接口、协议:SCCB

一、概述 SCCB(串行摄像头控制总线)是由欧姆尼图像技术公司&#xff08;OmniVision&#xff09;开发的一种类IIC的总线&#xff0c;主要用于其OV系列的图像传感器上&#xff08;但目前有很多家的图像传感器都有采用该控制总线&#xff09;。相对于IIC总线来说SCCB与之最主要的差…

Apache访问控制

服务器相关的访问控制 Options指令 Options指令是Apache服务器配置文件中的一个重要指令,它可以用于控制特定目录启用哪些服务器特性。Options指令可以在Apache服务器的核心配置、虚拟主机配置、特定目录配置以及.htaccess文件中使用。 以下是一些常用的服务器特性选项: N…

Rust语言特性探秘:宏的魔力

大家好&#xff01;我是lincyang。 今天我们继续深入探讨Rust语言中的一个有趣而强大的特性——宏&#xff08;Macros&#xff09;。 宏在Rust中扮演着特殊的角色&#xff0c;不仅提高了代码的灵活性&#xff0c;还增强了代码的可重用性。接下来&#xff0c;我们会通过具体的…

如何在Ubuntu的Linux系统中安装MySQL5.7数据库

前往MySQL数据库官网链接地址下载5.7数据库。 MySQL :: Download MySQL Community Server (Archived Versions)使用ssh的可视化工具将下载的mysql-5.7.40-linux-glibc2.12-x86_64.tar.gz文件上传到Linux服务器&#xff0c;并解压文件 tar -zxvf mysql-5.7.40-linux-glibc2.12-x…

云计算实验如何结合AI来提高效率!

随着AI助手的流行&#xff0c;我们现在无论是学习还是工作都会带着一个他/她&#xff0c;如何让AI助手提高我们的工作效率是我们需要进化的方向。下面结合“云计算实验”来分享一下如何让AI帮助我们学得更快学得更好。 一、学习某个软件或复杂命令 比如在学习RockyLinux9.2中…

汇编-pop出栈指令

32位汇编 执行动作分为两步&#xff1a; 第一步&#xff1a;读出数据 第二步&#xff1a;改变栈地址 如果操作数是16位&#xff0c; 则ESP加2&#xff1b; 如果操作数是32位&#xff0c; 则ESP加4 espesp2 或 espesp4 格式&#xff1a;

Windows 11电脑麦克风设置中缺少增强属性

下载安装第三方软件&#xff0c;地址 https://dev.azure.com/NVIDIACorp/NVIDIAControlPanel 使用第三方软件的增强功能。

中职组网络安全 Server-Hun-1.img Server-Hun-2.img

一串密码 smbuser用户和密码登录ssh还是失败提示需要密钥&#xff0c;尝试ftp登录成功 发现密钥存放在.ssh/下&#xff0c;在kali上生成一个密钥&#xff0c;通过上传到.ssh/下&#xff0c;将其替换掉 使用kali生成密钥 登录成功,但是无法拿到root目录下的flag 获取root用户权限…

Visual Studio(VS) C++程序LNK2005错误,提示“error LNK2005: _XXX已经在xxx.obj中定义”解决方案

1.问题如图 2.出现原因 项目中有多个源文件或头文件&#xff0c;include后导致有些变量重复定义&#xff0c;加上Visual Studio新版版要求更严格 3.解决办法 查询到的解决办法很多不好用&#xff0c;此处记录解决自己问题的一个办法&#xff1a;直接让编译器忽略第二次定义的…