搞清楚linux系统中MMU和mmap区别

        首先MMU(Memory Management Unit)它是一块硬件单元,通常集成在CPU 或 SoC 中。主要功能是把“虚拟地址”转换为“物理地址”

        mmap(memory map)它是操作系统内核提供的一个系统调用/软件机制。用于将一个文件或设备缓冲区映射到进程的虚拟地址空间里

        可以直观的看出来前者是硬件后者是软件上的机制,更关键的是MMU是介于硬件层与内核层之间的,而mmap是介于应用层与内核层之间的。它们所负责的位置不同。

MMU       

        MMU通常并不是你在板子上能找到的独立芯片,而是作为处理器(CPU/SoC)内核里集成的一块电路逻辑单元:集成在 CPU/SoC 内。在现代 x86、ARM、RISC‑V 等架构里,MMU 是 CPU 核心的一部分。它和算术逻辑单元、缓存(L1/L2/L3)一起,都是硅片(Silicon)上同一颗芯片(SoC)内部电路

        操作系统在内存中构建并维护好“虚拟页 → 物理页框”映射的多级页表MMU 硬件 从一个特殊寄存器(TTBR/CR3)拿到页表根地址,再按虚拟地址的各段位做多级索引,最终得到对应的物理页框号,中途结果缓存在 TLB 中,从而实现地址转换。

mmap

        mmap 是用户态与文件/设备打交道的映射接口,借助 MMU 做页表映射 。

        讲到mmap,最重要是的知道它干了什么,它最大的作用是让我们的线程、进程运行时,大大减少了我们数据拷贝的次数,提高了系统的实时性和效率。

        对于文件,内核会将文件内容按页(4 KiB 一页)加载到页缓存,执行 mmap(fd, length, prot, flags, fd, 0) 时,内核不会马上做任何数据拷贝,而是记录一个映射关系:把进程的虚拟地址区间 [addr, addr+length) 映射到文件页缓存对应的物理页上。进程首次访问映射区时(读或写),会触发一次缺页中断

        内核在缺页处理函数里:如果对应页已在页缓存,就直接把该物理页的页框(frame)分配给进程的页表;如果不在页缓存,就先从磁盘/外设载入到页缓存,再建立映射。

        从此以后,用户空间对映射区域的内存读写,就直接走 CPU 的常规读写路径,经由 MMU → TLB,访问那块已经映射的物理页,不会再经过 read()/write() 系统调用路径,也就省去了两次拷贝。

下面是mmap部分代码示例,分别是应用层与内核层的关键函数

//应用层中mmap映射函数


fd = open("/dev/led", O_RDWR);//打开设备文件,内核就能获取设备文件的索引节点,填充inode结构
	if(fd<0){
		printf("open error,fd = %d\n",fd);
		return -1;
	}
buffer = (char *)malloc(1024);
	memset(buffer, 0, 1024);
	mapBuf = mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);//内存映射,会调用驱动的mmap函数
	strcpy(mapBuf, "test data for mmap");//向映射段写数据
	memset(buffer, 0, 1024);   //清空,避免误判
	strcpy(buffer, mapBuf);    //从映射段读取数据
	printf("read data is %s\n", buffer);//如果读与写一致,说明映射成功
	munmap(mapBuf, 1024);//解除映射
	free(buffer);
//内核层中mmap映射函数

static int device_mmap(struct file *file, struct vm_area_struct *vma)
{
  vma->vm_flags |= VM_IO;//表示对设备IO空间的映射
  vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);//标志该内存区不能被换出,在设备驱动中虚拟页和物理页的关系应该是长期的,应该保留起来,不能随便被别的虚拟页换出

   if(remap_pfn_range(vma,//虚拟内存区域,即设备地址将要映射到这里
	   vma->vm_start,//虚拟空间的起始地址
            virt_to_phys(buf)>>PAGE_SHIFT,//与物理内存对应的页帧号,物理地址右移12位
            vma->vm_end - vma->vm_start,//映射区域大小,一般是页大小的整数倍
          vma->vm_page_prot))//保护属性,
   {
	return -EAGAIN;
   }
return 0;

注意这个过程没有“新开辟一块内存”

        驱动里通常已经通过 kmalloc/dma_alloc_coherent、或者是 MMIO 的物理基址(BAR)准备好了一段物理内存。mmap 并不额外分配新的页;它只是把这些已有的物理页,映射(map)到用户进程的页表中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值