mmap匿名映射

mmap函数创建匿名映射区 mmap函数创建匿名映射区 mmap一般创建思路 1,打开一个文件,得到该文件的文件描述符 int fd = open(char *path,int mode) 2, 创建该文件的内存映射区 void *mptr = mmap(void *addr,size_t len,int prot,int mode,ssize_t fd,size_t offset); addr ------- NUL... 阅读详情
AI摘要

本文介绍mmap匿名映射的概念及其在父子进程间通信的应用,通过两种方式实现匿名映射:使用fd=-1及通过/dev/zero设备文件。详细展示了代码示例,解释如何利用匿名映射实现数据共享。

一、原理

mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。

进程在用户空间调用库函数mmap,原型:void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);来实现内存映射。

从原型可知,存在一个参数为fd,根据fd,存在一种情况叫匿名映射,所谓匿名映射,表示不存在fd这么个真实的文件。实现匿名映射的方式主要有以下两种:
1、BSD 提供匿名映射的办法是fd =-1,同时 flag 指定为MAP_SHARE|MAP_ANON。
      ptr = mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,
                  MAP_SHARED|MAP_ANON,-1,0);

2、SVR4 提供匿名映射的办法是 open  /dev/zero设备文件,把返回的文件描述符,作为mmap的fd参数。
      fd = open("/dev/zero",O_RDWR);
/dev/zero 是一个特殊的文件,当你读它的时候,它会提供无限的空字符(NULL, ASCII NUL, 0x00)
 一个作用是用它作为源,产生一个特定大小的空白文件。

匿名内存映射适用于具有亲属关系的进程之间;由于父子进程之间的这种特殊的父子关系,在父进程中先调用mmap(),然后调用fork(),那么,在调用fork() 之后,子进程继承了父进程的所有资源,当然也包括匿名映射后的地址空间和mmap()返回的地址,这样父子进程就可以通过映射区域进行通信了;

这里不是一般的继承关系,一般来说,子进程单独维护从父进程继承下来的一些变量,而mmap()返回的地址却是由父子进程共同维护的;对于具有亲属关系的进程之间实现共享内存的最好方式应该是采用匿名映射的方式。此时,不必指定具体的条件,只要设置相应的标志即可。

二、代码

下面分别以匿名映射方式举例说明父子进程之间的通信:

1、fd=-1

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <semaphore.h>
 
struct file_content
{
    	sem_t st;
    	void *pv;
}file_content;
 

#define NINT 16

 
int main (int argc, char *argv[])
{
    	struct file_content *pfc;
    	pfc =mmap (NULL, sizeof (file_content) + sizeof (int) * NINT,
		PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);
 
    	if (pfc == MAP_FAILED)
      	{
	  	printf ("map failed!\n");
	  	exit(3);
      	}

	//信号量初始化为1,用于互斥
    	sem_init (&(pfc->st), 1, 1);		
	//pv指向结构体下一个字节的地址
    	pfc->pv = (void *) ((char *) pfc + sizeof (struct file_content));     
    	printf ("结构体地址:\t\t%x\n结构体下一位置地址:\t\t%x\n", (int)pfc, (int)pfc->pv);
 
	// 不加上这句的话,可能输出会卡在那里!
	setbuf(stdout,NULL); 

	//子进程
    	if (fork () == 0)		
      	{
	  	int i;
	  	while (1)
	    	{
			sem_wait (&(pfc->st));
			printf ("Child process\n");
			int *p = pfc->pv;
			for (i = 0; i < NINT; i++)
		  	{
		      		p[i] = 2 * i;
		  	}
			
			for (i = 0; i < NINT; i++)
		  	{
		      		printf ("%d ", p[i]);
		  	}
			printf ("\n"); 
			sem_post (&(pfc->st)); 
			sleep(2); 
	    	}
      	}
	// 父进程
    	else			
      	{
	  	int i;
	  	while (1)
	    	{
			sem_wait (&(pfc->st));
			printf ("Father process\n");
			int *p = pfc->pv;
			/*
			for (i = 0; i < NINT; i++)
		  	{
		      		p[i] = 3 * i;
		  	}
			*/
			
			for (i = 0; i < NINT; i++)
		  	{
		     		printf ("%d ", p[i]);
		  	}
			printf ("\n");
			sem_post (&(pfc->st));
			sleep(2);
	    	}
      	}

    	if (munmap (pfc, sizeof (file_content) + sizeof (int) * NINT) == -1)
      	{
	  	printf ("ummap!\n");
	  	exit (2);
      	}
    	return 0;
}

2、使用/dev/zero

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <semaphore.h>
 
struct file_content
{
    	sem_t st;
    	void *pv;
}file_content;
 

#define NINT 16
#define FILE_PATH "/dev/zero"

 
int main (int argc, char *argv[])
{

	int fd;
	fd = open(FILE_PATH,O_RDWR);
	if(fd < 0)
	{
		printf("open zero fail \n");
		exit(2);
	}
	
    	struct file_content *pfc;
    	pfc =mmap (NULL, sizeof (file_content) + sizeof (int) * NINT,
		PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANON, fd, 0);

	close(fd);
 
    	if (pfc == MAP_FAILED)
      	{
	  	printf ("map failed!\n");
	  	exit(3);
      	}

	//信号量初始化为1,用于互斥
    	sem_init (&(pfc->st), 1, 1);		
	//pv指向结构体下一个字节的地址
    	pfc->pv = (void *) ((char *) pfc + sizeof (struct file_content));     
    	printf ("结构体地址:\t\t%x\n结构体下一位置地址:\t\t%x\n", (int)pfc, (int)pfc->pv);
 
	// 不加上这句的话,可能输出会卡在那里!
	setbuf(stdout,NULL); 

	//子进程
    	if (fork () == 0)		
      	{
	  	int i;
	  	while (1)
	    	{
			sem_wait (&(pfc->st));
			printf ("Child process\n");
			int *p = pfc->pv;
			for (i = 0; i < NINT; i++)
		  	{
		      		p[i] = 2 * i;
		  	}
			
			for (i = 0; i < NINT; i++)
		  	{
		      		printf ("%d ", p[i]);
		  	}
			printf ("\n"); 
			sem_post (&(pfc->st)); 
			sleep(2); 
	    	}
      	}
	// 父进程
    	else			
      	{
	  	int i;
	  	while (1)
	    	{
			sem_wait (&(pfc->st));
			printf ("Father process\n");
			int *p = pfc->pv;
			/*
			for (i = 0; i < NINT; i++)
		  	{
		      		p[i] = 3 * i;
		  	}
			*/
			
			for (i = 0; i < NINT; i++)
		  	{
		     		printf ("%d ", p[i]);
		  	}
			printf ("\n");
			sem_post (&(pfc->st));
			sleep(2);
	    	}
      	}

    	if (munmap (pfc, sizeof (file_content) + sizeof (int) * NINT) == -1)
      	{
	  	printf ("ummap!\n");
	  	exit (2);
      	}
    	return 0;
}

通过上述代码即可通过匿名内存映射的方式实现父子进程之间的通信,程序执行结果如下图所示:

父子进程对于匿名映射空间的修改都会被彼此所见,通过这样一段共享内存,实现了父子进程之间的通信。

 

Linux系统 mmap 存储映射 括号中表示预期行为,括号外部的表示在LINUX系统中的实际行为,比如组合SHARED/EXEC的读行为,对于一个可执行的共享地址来说,没有给与PROT_READ属性,预期当然不可读,但是由于CPU执行上面的代码,必须要进行读操作,而实际的硬件架构和及并没有区分执行读和其它方式的读,所以,实际上对于这样的内存,仍然是可读的。从上图中可以看到,这段匿名区域(可能是MMAP区域,现在的MALLOC都用MMAP实现)地址是向下增长的,像栈一样,就像前面提到的第二种情况,这是在哪里控制的呢? 阅读详情

相关推荐

Linux内存管理架构之四(mmap内存映射机制)

mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。答 : 文件答大小对映区操作有影响. 虽然当文件原内容大于申请范围,但是越界数小于文件原内容大小,不会出现问题. 但是不建议这样做.尽量使文件和申请大小相同并且在申请的大小内操作.

weixin_39077305的博客 3391

linux内存管理笔记(三十四)----匿名映射

匿名内存是用户空间的概念,不涉及内核态内存。匿名内存的概念是指一段虚拟内存映射是否与之相关联的对象,如果没有关联对象就称为匿名的。本章就主要学习缺页异常的匿名映射,其中涉及到以下内容 匿名映射的概念 匿名映射的流程 1. 概念 由于应用程序申请内存后,内核分配了虚拟内存,当访问所需要的的内存时候,才会分配实际的物理内存,才能节省实际内存的使用。我们来看看匿名映射和文件映射的区别 匿名页面,是指那些没有关联到文件页,如进程堆、栈、数据段和任务已修改的共享库等,不是以文件形式存在,因此无法和磁盘文件交换

奇小葩 7867

Linux系统编程:告别临时文件——详解 mmap 匿名映射

摘要:本文介绍了匿名内存映射(MAP_ANONYMOUS)在父子进程间通信的高效实现方式。相比传统基于文件的mmap通信,匿名映射无需创建物理文件,直接在内核空间分配共享内存区域。通过代码示例演示了父子进程如何利用MAP_SHARED标志共享内存,并对比分析了MAP_PRIVATE的写时复制特性。文章还提供了兼容性方案——使用/dev/zero设备文件实现类似功能。该方法避免了临时文件清理问题,特别适合血缘进程间的轻量化数据共享,但需注意仅适用于Linux系统且有血缘关系的进程间通信场景。

Web安全工具库 877

Linux内存映射函数mmap与匿名内存块

memory-mapped io可以将文件映射到内存中的buffer,当我们从buffer读写数据时,其实操作的是对应文件中的数据。这样可以达到不使用READ/WRITE的IO操作。 mmap也可以直接映射匿名内存块,无需提供文件fd,直接申请一块内存给当前进程使用,也可以选择继承给子进程。

InternalsOf 1898

mmap详解

想写一篇文章,详细的介绍一下mmap,主要是原理、用法、mmap泄露来进行介绍。说到mmap,首先得从堆空间说起。

weixin_42136255的博客 2037

[deprecated]linux mmap 的匿名映射和设备映射

本文深入探讨了Linux系统中mmap匿名映射的内存管理机制及其应用。文章首先分析了虚拟地址空间布局和VMA关键数据结构,详细阐述了缺页中断、请求调页和写时复制等底层实现原理。通过对mmap函数参数和内存分配流程的解析,揭示了匿名映射与malloc在实现机制、性能特点和适用场景上的核心差异。重点介绍了mmap在多进程共享内存和GPU零拷贝数据传输等高级应用场景中的优化实践,最后展望了大页支持、内存压缩等未来发展方向。文章通过系统性的技术分析和实践示例,为开发者深入理解Linux内存管理提供了全面指导。

图形/计算GPU的驱动与虚拟化技术分享园地 925

Linux C++系统编程:使用mmap创建匿名映射区

本文介绍了Linux C++中使用mmap创建匿名映射区的方法。mmap系统调用通过MAP_ANONYMOUS标志创建不依赖文件的匿名映射,相比文件映射更适合进程间通信和大内存分配。文章详细讲解了mmap参数配置、内存保护设置、共享映射实现以及大页内存等高级用法,并与传统内存分配进行了性能对比。此外还提供了C++封装类示例,实现了RAII管理映射内存。匿名映射适用于需要大块内存、进程间共享或特殊内存需求的场景,使用时需注意边界检查、权限控制和及时释放等安全问题。

软件科学-郝学胜 1802

ZYNQ实战:PS端驱动DMA实现高效数据流转与验证

本文详细介绍了在ZYNQ平台上通过PS端驱动DMA实现高效数据流转的实战方法。从ZYNQ的PS与PL数据交互基础出发,深入解析DMA核心价值,包括硬件平台搭建、Vivado配置、PS端软件架构设计及性能优化技巧,帮助开发者提升数据传输效率与系统性能。

weixin_29192141的博客 433

mmap匿名映射区

里所谓的内存其实指的是虚拟内存,在调用 mmap 进行匿名映射的时候(比如进行堆内存的分配),是将进程虚拟内存空间中的某一段虚拟内存区域与物理内存中的匿名内存页进行映射,当调用 mmap 进行文件映射的时候,是将进程虚拟内存空间中的某一段虚拟内存区域与磁盘中某个文件中的某段区域进行映射。在创建映射区时,我们创建了一个文件,后面又需要unlink删除,然后munmap释放内存映射区,所以一开始就没必要创建。局限性:匿名映射只能用于有血缘关系的进程之间,因为之间共享内存,其他进程因为没有指定名字,那没法通信。

dont worry about it的博客 3万+

基于的公司考勤系统(程序+开题报告)(开题报告+源码)

我们将研究和设计系统的架构和功能模块,包括员工信息管理模块、部门信息管理模块、考勤信息记录模块、工资信息计算模块、请假信息处理模块、奖惩信息管理模块、公告信息发布模块、上班打卡模块以及加班申请模块等。目的: 本项目旨在设计并实现一个基于的公司考勤系统,通过该系统,可以实现对员工、部门信息、考勤信息、工资信息、请假信息、奖惩信息、公告信息、上班打卡、加班申请等功能的统一管理。基于的公司考勤系统的设计与实现,旨在通过自动化技术提高考勤管理的效率和准确性,为企业管理提供有力的数据支持。最终成品以下面运行环境。

迟限程序设计 997

ArcGIS Pro样式导入全攻略:从.style到.stylx的完整转换流程(附常见问题解决)

本文详细解析了ArcGIS Pro中从旧版.style文件导入并转换为新版.stylx格式的完整流程。针对用户在迁移过程中常见的样式库为空、符号匹配失败、显示异常等问题,提供了清晰的排查思路与解决方案,帮助用户高效完成样式库的升级与迁移,确保制图工作的连续性。

raspberrypi5的博客 515

16LinuxC进程间通信之mmap创建匿名映射区

1 mmap创建匿名映射区 创建匿名映射区非常简单,只需要加上MAP_ANONYMOUS即可,参数len长度可以随便大小,fd没有传-1即可。open这些函数可以不需要了,并且匿名映射实际上就是解决中间创建的文件问题。 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #include <sys

weixin_44517656的博客 787

哈工大2021年秋季学期数据结构期末试题

因为考完试没有收演草纸,所以题中数据与考试差距不大。选项顺序可能略有差异;选择第5题希尔排序的序列数据是后编的;简答第3题B-树的插入序列顺序可能不同,但是考察的点是一样的。其他题的数据基本可以保证和原题一样。 一、选择题 111.以下代码的时间复杂度是 for(int k=1;k<=n;k++) for(int j=1;j<=n;j++) count++; A.O(n)       B.O(nlogn) &

Castria的博客 4271

#Linux内存管理# 详细介绍使用mmap函数创立共享匿名映射的工作原理

使用 mmap 创建共享匿名映射 - 详细解析与代码示例 共享匿名映射 (MAP_SHARED | MAP_ANONYMOUS) 允许不相关进程间建立高效的共享内存通信机制: 不涉及磁盘文件,纯内存通信 使用 MAP_ANONYMOUS 标志,忽略文件描述符 内核直接分配匿名物理内存页 页内容初始化为零 不同进程的虚拟地址映射到相同物理内存页 映射地址在不同进程中通常不同 进程间通信绕过内核缓冲 比管道/套接字快10-100倍 适合高频、低延迟场景 映射自动释放 内存

sinat_37817094的博客 1023

Synopsys PCIe IP Loopback功能深度解析与应用实践

本文深入解析了Synopsys PCIe IP的Loopback功能,包括本地数字环回和远程环回两种模式的应用实践。通过详细的寄存器配置步骤和实战案例,帮助开发者快速掌握PCIe芯片验证与调试技术,提升系统开发效率。特别适合PCIe协议相关的硬件工程师和验证工程师参考。

weixin_29198045的博客 530

Altium Designer(AD)仿真实验操作指南

1:运行仿真2:设置仿真3:放置电源模块4:放置器件模块5:探针。

XU157303764的博客 8891

linux学习第24天(mmap建立父子间通信、无血缘关系进程间通信、匿名映射)

前面是写,后面是读一个读,一个写。

2301_80728863的博客 515

Linux内核配置选项详解及编译过程

在内核编译完成后,可以通过重启系统并选择新编译的内核来使用它。可以在该菜单下选择需要编译进内核的设备驱动,也可以选择将设备驱动编译为模块。可以在该菜单下选择需要编译进内核的设备驱动,也可以选择将设备驱动编译为模块。可以选择需要的调试选项,并根据需要启用或禁用相应的功能。可以选择需要的文件系统类型,并根据需要启用或禁用相应的选项。可以选择需要的网络协议和功能,并根据需要启用或禁用相应的选项。可以选择需要的调试选项,并根据需要启用或禁用相应的功能。可以选择需要的文件系统类型,并根据需要启用或禁用相应的选项。

TechGlide的博客 746

linux+mmap父子通信_Linux内核虚拟内存管理之匿名映射缺页异常分析

韩传华,就职于南京大鱼半导体有限公司,主要从事linux相关系统软件开发工作,负责Soc芯片BringUp及系统软件开发,乐于分享喜欢学习,喜欢专研Linux内核源代码。前面讲到过写时复制缺页异常(COW),一般用于父子进程之间共享页,而我们会常见一种缺页异常是匿名映射缺页异常,今天我们就来讨论下这种缺页异常,让大家彻底理解它。注:本文使用linux-5.0内核源代码。文章分为以下几节内容:1.匿...

weixin_36467992的博客 473

手把手教你学simulink(31.31)--双向DCDC电源场景示例:设计并实现一个基于变频控制的双向降压变换

设计并实现一个基于 Simulink 的双向降压变换器,能够在充电模式(从高压侧向低压侧传输能量)和放电模式(从低压侧向高压侧传输能量)之间切换,确保输出电压稳定,并根据负载变化自动调整工作模式。

MHD0815的博客 343

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【Linux mmap 文件映射】从虚拟地址到页缓存:读写文件、匿名映射与极简 malloc

PROT_READ:允许读;PROT_WRITE:允许写;PROT_EXEC:允许执行;PROT_NONE:暂时不可访问。权限既要符合业务意图,也要与文件打开方式兼容。例如,对文件建立可写MAP_SHARED映射时,描述符通常必须以O_RDWR打开;否则mmap可能以EACCES失败。安全上应遵循最小权限原则:只读数据不要添加PROT_WRITE,普通数据不要添加PROT_EXEC。文件长度通常不是页大小的整数倍。[0, 4096) 完整页[4096, 8192) 完整页。

星光编译者的技术博客,专注 C/C++、Linux、数据结构与算法。 276

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Linux——mmap函数、父子进程间mmap通信、无血缘关系间mmap通信、mmap匿名映射区

一、存储映射I/O(磁盘内容映射到内存) 一、概念理解 存储映射I/O(Memory-mapped I/O)使一个磁盘文件与存储空间中的一个缓冲区相映射。于是当从缓冲区中取数据,就相当于读文件中的相应字节。与此类似,将数据存入缓冲区,则相应的字节就自动写入文件。这样,就可以在不使用read和write函数的情况下,使用地址(指针)完成I/O操作。 (本来在磁盘上的内容,想要去读写就需要open打开...

qq_37299596的博客 1551

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Linux系统编程---5(共享存储映射,存储映射I/O,mmap函数,父子进程间通信,匿名映射)

共享存储映射 文件进程间通信 使用文件也可以完成 IPC,理论依据是,fork 后,父子进程共享文件描述符。也就共享打开的文件。 编程:父子进程共享打开的文件。借助文件进行进程间通信。 测试代码 /* * * 父子进程共享打开的文件描述符----使用文件完成进程间通信 * */ #include<stdio.h> #include<unistd.h> #inclu...

LXY的博客 831

mmap内核源码分析

对于mmap函数,我之前的理解太单一了。这几天好好复习了一下以前学过的知识,重新对该函数有了新的认识。之前我的认识是,mmap是用来映射内存的,它映射的内存来自磁盘上文件。所以我以为malloc函数底层也映射文件内存。后来一直想不通。实际上,mmap函数再malloc底层实现中采用了匿名映射(就是这个匿名映射,我之前一直概念不清)。先说下malloc调用mmap一般的形式://原型 //mmap(v

FreeeLinux's blog 3433

OK6410A 开发板 (八) 102 linux-5.11 OK6410A glibc提供的mmap的四种用途之一 共享匿名映射两种实例与共享文件映射dev-zero

共享匿名映射实例 mmap_negtivefd.c 当使用参数 fd = -1 且 flags = MAP_ANONYMOUS | MAP_SHARED 时,创建的mmap 映射是共享匿名映射. 共享匿名映射让相关进程共享一块内存区域,通常用于父子进程之间的通信. 创建共享匿名映射有如下两种方式,这两种方法最终都调用shmem 模块来创建共享匿名映射 1. fd = -1,且 使用这个文件句柄来创建mmap(lags = MAP_ANONYMOUS | MAP_SHARED) . 在这种情况下,.

u011011827的博客 357

【内存管理与高并发内存池系列】从 mmap 到 malloc:文件映射、匿名映射与 glibc 内存分配机制详解

本文探讨了从传统文件I/O到mmap内存映射的技术演进。传统read/write方式通过系统调用访问文件,涉及用户态/内核态切换和数据拷贝开销。而mmap通过将文件映射到进程虚拟地址空间,实现零拷贝访问。文章详解了open系统调用的路径解析过程(dentry→inode→struct file)和read操作的文件页管理机制(page cache与address_space)。mmap利用虚拟内存机制,仅在访问时触发缺页异常加载文件数据到page cache,避免了频繁系统调用和数据复制,特别适合大文件高频

努力努力再努力wz的博客 618
上一篇: Linux中的随机数
下一篇: 使用Source Insight查看内核源码
SweeNeil
博客等级 码龄9年 251粉丝 86原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值