内存映射原理

1. 内存映射原理

1.1 什么是映射?

“映射”这个词,就和数学课上说的“一一映射”是一个意思,就是建立一种一一对应关系

1.2 内存映射原理通俗理解

通俗说就是:在这里主要是将硬盘上文件的位置与进程逻辑地址空间(其实就是32位下的4GB虚拟地址空间)中一块大小相同的区域之间的一一对应。

关于虚拟地址,请参考之前的博客:
从操作系统角度看可执行文件的装载:进程建立的3个步骤,虚拟地址空间,页错误
https://blog.csdn.net/lqy971966/article/details/106910746

1.3 内存映射原理-mmap

  1. 逻辑的概念
    这种对应关系纯属是逻辑上的概念,物理上是不存在的,原因是进程的逻辑地址空间本身就是不存在的
    在内存映射的过程中,并没有实际的数据拷贝,文件没有被载入内存,只是逻辑上被放入了内存

  2. mmap
    具体到代码,就是建立并初始化了相关的数据结构 (struct address_space),
    这个过程有系统调用 mmap() 实现,所以建立内存映射的效率很高

mmap()会返回一个指针ptr,它指向进程逻辑地址空间中的一个地址,这样以后,只需要通过ptr就能够操作文件

2. 内存映射文件原理原理图:非常棒!!!

参考这个博客即可
https://blog.csdn.net/mengxingyuanlove/article/details/50986092

3. mmap munmap 参数详解:

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);
  1. addr:虚拟地址
    如果不为 NULL,内核会在此地址创建映射;否则,内核会选择一个合适的虚拟地址。
    大部分情况不指定虚拟地址,意义不大,而是让内核选择返回一个地址给用户空间使用。

  2. length:表示映射到进程地址空间的大小。

  3. prot:内存区域的读/写/执行属性。
    下面是prot对应的参数组合:

    #define PROT_READ 0x1 /* page can be read /
    #define PROT_WRITE 0x2 /
    page can be written /
    #define PROT_EXEC 0x4 /
    page can be executed /
    #define PROT_SEM 0x8 /
    page may be used for atomic ops /
    #define PROT_NONE 0x0 /
    page can not be accessed /
    #define PROT_GROWSDOWN 0x01000000 /
    mprotect flag: extend change to start of growsdown vma /
    #define PROT_GROWSUP 0x02000000 /
    mprotect flag: extend change to end of growsup vma */

  4. flags:内存映射的属性,共享、私有、匿名、文件等。

    #define MAP_SHARED 0x01 /* Share changes /
    /
    创建一个共享映射的区域,多个进程可以映射到一个文件.
    其他进程可以看到映射内容的改变,修改后内容会同步到磁盘中。/
    #define MAP_PRIVATE 0x02 /
    Changes are private /
    /
    创建一个私有的写时复制的映射,其他进程看不到映射内容的改变,也不会同步到磁盘中。*/

  5. fd:表示这是一个文件映射,fd是打开文件的句柄。
    如果是文件映射,需要指定fd;匿名映射就指定一个特殊的-1。

  6. offset:在文件映射时,表示相对文件头的偏移量;返回的地址是偏移量对应的虚拟地址。

参考:
https://www.cnblogs.com/arnoldlu/p/8330785.html
https://www.cnblogs.com/arnoldlu/p/9367253.html

4.代码示例

#include <sys/mman.h>
#include <sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<error.h>

int main(int argc, char * argv[])
{
	int fd, nread;
	struct stat sb;
	char *mapped;

	//打开文件
	if((fd = open(argv[1], O_RDWR)) < 0){
		perror("open") ;
	}   

	//获取文件的属性
	if((fstat(fd, &sb)) == -1 ){
		perror("fstat") ;
	}   
	
	
	//将文件映射至进程的地址空间
	if((mapped = mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) ==(void*) -1){
		perror("mmap") ;
	}   
	
	//修改一个字符,同步到磁盘文件
	mapped[20] = '9';
	if((msync((void *)mapped, sb.st_size, MS_SYNC)) == -1){
		perror("msync") ;
	
		//释放存储映射区
		if((munmap((void *)mapped,sb.st_size)) == -1){
			perror("munmap");  
		}   
	}
				
	return 0;
}


[root@localhost home]# cat test.txt 
aaaaaaaaa
bbbbbbbbb
cccccccccccc
ddddddddd

执行:

[root@localhost home]# ./a.out test.txt 
[root@localhost home]# cat test.txt 
aaaaaaaaa
bbbbbbbbb
9ccccccccccc
ddddddddd
[root@localhost home]#

参考:
https://blog.csdn.net/whatday/article/details/89239331

参考:

原理图:
https://blog.csdn.net/mengxingyuanlove/article/details/50986092
参数详解
https://www.cnblogs.com/arnoldlu/p/9367253.html
https://www.cnblogs.com/arnoldlu/p/8330785.html
代码示例:
https://blog.csdn.net/whatday/article/details/89239331

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值