内存映射机制

什么是内存映射

Linux通过将一个虚拟内存区域与一个磁盘上的对象关联起来,以初始化这个虚拟区域的内如,这个过程称为内存映射。

代码示例:

/*******************************************************************
 *   > File Name: mmap.c
 *   > Create Time: 2021年09月28日 星期二 19时30分22秒
 ******************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

int main(int argc, char* argv[])
{
    int fd = open("test.txt", O_RDWR); // 打开文件test.txt
    if (fd < 0)
    {
        perror("open file faild!");
        return -1;
    }
    char *start = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if(start == MAP_FAILED){
        perror("mmap faild");
        return -1;
    }

    printf("%s\n", start); // 输出内存内容
    char t[] = "helloword!\n";
    memcpy(start, t, sizeof(t));
    munmap(start, 4096); // 解除内存映射
    close(fd); // 关闭文件

    return 0;
}

内存映射原理

分析效率

从代码层面上看,从硬盘上将文件读入内存,都要经过文件系统进行数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一样的。但是通过内存映射的方法访问硬盘上的文件,效率要比read和write系统调用高,这是为什么呢?原因是read()是系统调用,其中进行了数据拷贝,它首先将文件内容从硬盘拷贝到内核空间的一个缓冲区,如图2中过程1,然后再将这些数据拷贝到用户空间,如图2中过程2,在这个过程中,实际上完成了 两次数据拷贝 ;而mmap()也是系统调用,如前所述,mmap()中没有进行数据拷贝,真正的数据拷贝是在缺页中断处理时进行的,由于mmap()将文件直接映射到用户空间,所以中断处理函数根据这个映射关系,直接将文件从硬盘拷贝到用户空间,只进行了 一次数据拷贝 。因此,内存映射的效率要比read/write效率高

内存映射的特点

  • 不会在映射的时候分配物理页
  • 仅仅是建立一种关联
    • 虚拟地址和文件地址偏移建立关联
    • 设置好缺页异常回调函数
    • 返回分配的虚拟地址给用户程序
  • 读写的时候触发缺页异常

再看fork函数

当fork函数被当前进程调用的时候,内核为新进程创建各种数据结构,并分配一个唯一ID,为了给这个新进程创建虚拟内存,它创建当前进程的mm_struct、区域结构和页表的原样副本。它将两个进程中的每个页面都标记为只读,并将两个进程中的每个区域结构都标记为私有的写时复制。当fork函数返回的时候,新进程现在的虚拟内存和调用的时候完全一样,当两个进程中的任何一个进行写的时候,写时复制机制会创建新的页面

再看execve函数

例如:execve("wc",NULL,NULL) 

加载并运行wc需要以下几步:

  • 删除已存在的用户区域

删除当前进程虚拟地址的用户部分已存在的区域结构。

  • 映射私有区域

为新程序的代码、数据、bss、和栈区域创建新的区域结构,所有这些新的区域结构都是私有的、写时复制的

  • 映射共享区域

如果wc还需要链接一些其他目标,比如C标准库中的libc.so,这些对象都是动态链接到程序中,然后再映射到用户虚拟地址空间中的共享区域内

  • 设置程序计数器 

execve做的最后一件事情,就是设置当前进程的上下文的程序计数器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值