Linux系统编程——共享内存映射(进程间通信)

news2024/11/27 16:16:44

目录

  • mmap函数
    • 1.函数原型
    • 2.建立映射区
    • 3.注意事项
    • 4.父子进程间mmap通信
    • 4.无血缘关系进程间mmap通信
      • 写进程:
      • 读进程:
  • 附:文件用于进程间通信

mmap函数

1.函数原型

  • void *mmap(void *addr,size_t length, int prot,int flags, int fd,off_t
    offset);
    创建共享内存映射

参数:

  • addr:指定映射区的首地址。通常传NULL,表示让系统自动分配
  • length:共享内存映射区的大小
  • prot:共享内存映射区的读写属性。PROT_READ、PROT_YRITE、PROT_READ、PROT__RITE
  • flags:标注共享内存的共享属性。MAP_SHARED、IAP_PRIVATE
  • fd:用于创建共亨内存映射区的那个文件的文件描述符。
  • offset:偏移位置。需是4的整数倍。

返回值:

  • 成功:映射区的首地址。
  • 失败:MAP_FAILED , errno

2.建立映射区

  • int manmap(void *addr,size_t length);
    释放映射区。
  • addr: mmap的返回值
  • length:大小
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>

void sys_err(const char *str)
{
	perror(str);
	exit(1);
}
int main(int argc,char *argv[])
{
	char *p = NULL;
	int fd;
	fd = open("testmap",O_RDWR|O_CREAT|O_TRUNC,0664);
	if(fd == -1)
	{
		sys_err("open error");
	}
/*
	lseek(fd,10,SEEK_END);
	write(fd,"\0",1);
*/
	ftruncate(fd,20);
	int len = lseek(fd,0,SEEK_END);
	p = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
	if(p == MAP_FAILED)
	{
		sys_err("mmap error");
	}
	//使用p对文件进行读写操作
	strcpy(p,"hello mmap");
	printf("-----%s\n",p);
	int ret = munmap(p,len);
	if(ret == -1)
	{
		sys_err("munmap error");
	}
	return 0;
}

3.注意事项

  • 1.用于创建映射区的文件大小为0,实际指定非0大小创建映射区,出“总线错误”。
  • 2.用于创建映射区的文件大小为0,实际制定0大小创建映射区,出“无效参数”。
  • 3.用于创建映射区的文件读写属性为,只读。映射区属性为读、写。出“无效参数”。
  • 4.创建映射区,需要read权限。当访问权限指定为“共享”MAP_SHARED是, mmap的读写权限,应该<=文件的open权限。只写不行。
  • 5.文件描述符fd,在mmap创建映射区完成即可关闭。后续访问文件,用地址访间。
  • 6.offset 必须是4096的整数倍。(MMU映射的最小单位4 )
  • 7.对申请的映射区内存,不能越界访问。
  • 8.munmap用于释放的地址,必须是mmap申请返回的地址。
  • 9.映射区访问权限为“私有”MAP_PRIVATE,对内存所做的所有修改,只在内存有效,不会反应到物理磁盘上。
  • 10.映射区访问权限为“私有”MAP_PRIVATE,只需要open文件时,有读权限,用于创建映射区即可。

4.父子进程间mmap通信

  1. 父进程先创建映射区。open ( O_RDWR)map( MAP_SHARED ) ;
  2. 指定MAP_SHARED权限
  3. fork()创建子进程。
  4. 一个进程读,另外一个进程写。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
int var = 200;
void sys_err(const char *str)
{
	perror(str);
	exit(1);
}
int main(int argc,char *argv[])
{
	int *p;
	pid_t = pid;
	int fd;
	fd = open("testmap",O_RDWR|O_CREAT|O_TRUNC,0664);
	if(fd == -1)
	{
		sys_err("open error");
	}
	ftruncate(fd,20);
	p = (int *)mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
	if(p == MAP_FAILED)
	{
		sys_err("mmap error");
	}
	close(fd);			//映射区创建完毕,即可关闭文件
	pid = fork();		//创建子进程
	if(pid == 0){		
		*p = 2000;		//写共享内存
		var = 1000;
	}else{				//父进程操作
		sleep(1);
		printf("parent,*p = %d,var = %d\n",*p,var);//读共享内存,var:读时共享,写时复制
		wait(NULL);
		int ret = munmap(p,len);//释放映射区
		if(ret == -1)
		{
			sys_err("munmap error");
		}	
	}
	return 0;
}

4.无血缘关系进程间mmap通信

  • 两个进程打开同一个文件,创建映射区。
  • 指定f1ags 为 MAP_SHARED。
  • 一个进程写入,另外一个进程读出。

【注意】﹔无血缘关系进程间通信。

  • mmap:数据可以重复读取。
  • fifo:数据只能一次读取。

写进程:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
struct student{
	int id;
	char name[25];
	int age;
};
void sys_err(const char *str)
{
	perror(str);
	exit(1);
}
int main(int argc,char *argv[])
{
	struct student stu = {110,"xiaom",18};
	struct student *p;
	int fd;
	fd = open("testmap",O_RDWR|O_CREAT|O_TRUNC,0664);
	if(fd == -1)
	{
		sys_err("open error");
	}
	ftruncate(fd,sizeof(stu));
	p = (struct student *)mmap(NULL,sizeof(stu),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
	if(p == MAP_FAILED)
	{
		sys_err("mmap error");
	}
	close(fd);			//映射区创建完毕,即可关闭文件
	while(1){
		memcpy(p,&stu,sizeof(stu));	
		stu.id++;
		sleep(1);
	}
	munmap(p,sizeof(stu));
	
	return 0;
}

读进程:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
struct student{
	int id;
	char name[25];
	int age;
};
void sys_err(const char *str)
{
	perror(str);
	exit(1);
}
int main(int argc,char *argv[])
{
	struct student stu;
	struct student *p;
	int fd;
	fd = open("testmap",O_RDWR|O_CREAT|O_TRUNC,0664);
	if(fd == -1)
	{
		sys_err("open error");
	}
	p = (struct student *)mmap(NULL,sizeof(stu),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
	if(p == MAP_FAILED)
	{
		sys_err("mmap error");
	}
	close(fd);			//映射区创建完毕,即可关闭文件
	while(1){
		printf("id = %d,name = %s,age = %d",p->id,p->name,p->age);
		sleep(1);
	}
	munmap(p,sizeof(stu));
	
	return 0;
}

附:文件用于进程间通信

一个进程对文件读,另一进程对文件写

在这里插入图片描述

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

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

相关文章

代码随想录训练营第五十六天

1.两个字符串的删除操作 题583 ①dp数组含义 由于有两个数组比较&#xff0c;所以用二维数组dp。dp[i] [j]表示以i-1为结尾的word1和以j-1为结尾的word2达到相等需要删除的元素的个数。 ②递推公式 两种情况&#xff0c;当word[i-1] word2[j-1]时&#xff0c;有没有i-1为结…

【Linux】gcc编译器的使用(程序的翻译过程)

目  录1 程序的翻译1.1预处理&#xff08;进行宏替换&#xff09;1.2 编译&#xff08;生成汇编代码&#xff09;1.3 汇编&#xff08;生成机器可识别代码&#xff09;1.4 链接&#xff08;生成可执行文件或者库文件&#xff09;1.5 gcc常用选项总结程序的翻译过程包括&#…

Diffie-Hellman密钥协商算法探究

作者 | 魔王赵二狗 导读 隐私计算&#xff08;Privacy-preserving computation&#xff09;是指在保证数据提供方不泄露原始数据的前提下&#xff0c;对数据进行分析计算的一系列信息技术&#xff0c;保障数据在流通与融合过程中的可用不可见。而Diffie–Hellman密钥协商是一种…

2023-01-10 mysql列存储引擎-聚合多线程并行扫表-VCPackGuardian策略LOCK_ALL-概要设计

摘要: 当前的pack淘汰策略为LOCK_ONE, 在多线程切换时导致pack地址丢失。 新设计LOCK_ALL策略以保证多线程聚合正常工作。 设计思想: 多线程聚合运算期间, 对持有的pack不做淘汰业务中对pack的读取和释放保持原有逻辑架构设计: 静态结构: 动态结构: 上层业务通过VirtualCol…

【学习笔记之Linux】工具之vim基本介绍

vim基本认识 vim是一种多模式的编辑器&#xff0c;它是vi的升级版本&#xff0c;它兼容vi所有的指令并加入了一些新的特性在里面。vi是一个老式的文本编辑器&#xff0c;功能相当齐全&#xff0c;vim则是在vi之上更进了一步&#xff0c;拥有代码补全、编译及错误跳转等功能&…

pytorch OutOfMemoryError

torch.cuda.OutOfMemoryError before: self.memory deque(maxlen50000) after: self.memory deque(maxlen500) ok.... pytorch模型提示超出内存cuda runtime error(2): out of memory - pytorch中文网 看到这个提示&#xff0c;表示您的GPU内存不足。由于我们经常在PyTo…

做外贸有没有好的软件?

在外贸电商行业中&#xff0c;邮件营销是非常重要的一种营销方式之一。除了性价比高&#xff0c;他还能对目标客户进行精准营销。但是&#xff0c;对于刚开始做的公司来讲&#xff0c;不注意方法和细节也难收获到理想的营销效果。 一、问题 1&#xff09;不管理邮箱联系人 只…

13.Isaac教程--模型制作

模型制作 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 该软件包演示了具有软件定义装配工作流程的工厂场景。 在模拟工厂环境中&#xff0c;多个 AMR 在装配站之间运输材料&#xff0c;而每个装配站的机械臂拾取所需材料并将其放置在对接的 …

自定义el-pagination分页

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; vue项目使用el-ui库&#xff0c;由于原本的el-pagination显示字段和样式无法满足其他项目的设计要求&#xff0c;需要进行改动 el-ui官网&#xff1a; 改动后&#xff1a; 解决方案&#xff1a; 1…

golang字符串常见功能

文章目录1. 获取字符串长度2. 是否一xx开头3. 是否以xx结尾4. 是否包含5. 变大写6. 变小写7. 去两边8. 替换9. 分割10. 拼接11. string转换为int12. int转换为string13. 字符串和字节切片14. 字符串和rune切片15. string和字符1. 获取字符串长度 2. 是否一xx开头 3. 是否以xx结…

抖音seo优化排名

武汉微驱动科技有限公司 你有没有想过&#xff0c;同样是运营抖音&#xff0c;为什么别人的视频总是排在你的前面&#xff1f;你死磕创意&#xff0c;拍摄、剪辑&#xff0c;甚至比同行更投入&#xff0c;为什么他的收益总是高于你&#xff1f; 当下抖音搜索引擎的用户数量已经…

Nginx与LUA(1)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e;HTTP服务器是相对于HTTP客户端来说的——HTTP客户端就是各种常用的「浏览器」&#xff0c;如IE、chrome、微信浏览器。当浏览器通过URL地址栏访问一个Web页面时&a…

【C++】STL六大组件之一——适配器(adapters)

目录1. 前言2. 初始适配器2.1 适配器的概念2.2 适配器的分类3. 容器适配器&#xff08;container adapters&#xff09;3.1 认识deque3.1.1 逻辑结构3.1.2 物理结构3.1.3 deque的迭代器3.1.4 选择deque做stack/queue底层容器的原因3.2 stack3.3 queue3.4 另一种容器适配器 ——…

阿里云计算巢 x GBase GCDW:自动化部署云原生数据仓库

近日&#xff0c;阿里云计算巢与天津南大通用数据技术股份有限公司&#xff08;以下简称&#xff1a;GBASE&#xff09;合作&#xff0c;双方融合各自技术优势&#xff0c;助力企业用户实现云上数据仓库的自动化部署&#xff0c;让用户在云端获取数据仓库服务“更简单”&#x…

【ESP32+freeRTOS学习笔记-(六)软件定时器】

目录1、软件定时器概念2、软件定时器的运行机制2.1 组成2.2 创建2.3 运行3、软件定时器的属性和状态3.1 定时器的周期3.2 定时器的类型3.3 定时器的状态4、软件定时器的回调函数原型5、定时器的使用5.1 创建定时器xTimeCreate()5.2 启动定时器xTimerStart()5.3 终止定时器xTime…

IPC进程间通信-system V 共享内存

&#x1f9f8;&#x1f9f8;&#x1f9f8;各位大佬大家好&#xff0c;我是猪皮兄弟&#x1f9f8;&#x1f9f8;&#x1f9f8; 文章目录一、共享内存原理二、共享内存的建立原理三、共享内存的创建四、共享内存的删除五、共享内存挂接到自己的地址空间六、从进程地址空间去掉与…

快过年了用Python抢红包

快过年了&#xff0c;刚刚收到了两个消息&#xff0c;一个好消息&#xff0c;一个坏消息。 先说好消息&#xff0c;好消息就是微信群里即将有人要发红包&#xff0c; 坏消息是我抢不上&#xff01; 难道就这么放弃了吗&#xff1f;那就只能试试能不能通过编程的方式实现自动化…

基于轻量级YOLOV5+BIFPN的苹果瑕疵检测识别分析系统

BIFPN是一种比较经典有效的特征融合手段&#xff0c;在很多检测模型中都有集成应用&#xff0c;实际表现也验证了BIFPN的有效性&#xff0c;这里并不是要探讨BIFPN的原理内容&#xff0c;而是想集成这项技术&#xff0c;提升原有模型的性能表现&#xff0c;在我之前的一些文章中…

排序算法之冒泡排序

一般学习过编程的人都知道&#xff0c;排序算法有很多种&#xff0c;包括直接选择排序、直接插入排序、计数排序、快速排序、归并排序、冒泡排序等&#xff0c;在我看来&#xff0c;以上六种排序算法是必须要掌握的&#xff0c;今天&#xff0c;我们先来讲解一下冒泡排序算法&a…

Java高手速成 | 新增类Record的工作实例

01、什么是Record? Record 是Java新增的库类&#xff0c;在Java 14和Java 15中以预览&#xff08;preview&#xff09;形式公布。Record类用来自动生成对定义数据进行创建、设置、访问以及比较等代码&#xff0c;所以又被称作数据类&#xff08;data class&#xff09;。在一…