Linux内核内存管理

Linux内核源码分析:内存管理子系统架构(用户空间、内核空间、硬件层面)
一、虚拟地址布局/内存映射
1、虚拟地址空间划分
1)用户虚拟地址空间布局
目前应用程序没有那么大的内存需求、所以ARM64处理器不支持完全的64位虚拟地址,虚拟地址的最大宽度是48位,如下图所示:
2)内核地址空间布局
ARM64处理器架构的内核地址空间布局如下图所示:
2、物理地址空间
物理地址是处理器在系统总线上看到的地址 。使用精简指令集(Set ,RISC)的处理顺路通常只一个物理地址空间,外围设备和物理内存使用统一的物理地址空间 。有些处理顺路架构把分配给外围设备的物理地址区域称为设备内存 。处理器通过外围设备控制器的寄存器访问外围设备,寄存器分为控制寄存器、状态寄存器和数据寄存器三大类,外围设备的寄存器通常被连续编址 。处理器对外围设备寄存器的编址方式有两种:I/O映射方式(I/O-)和内存映射方式(-) 。
程序只能通过虚拟地址访问外设寄存器,内核提供如下函数来把外设寄存器的物理地址映射到虚拟地址空间 。
a.函数ioremap()把外设寄存器的物理地址映射到内核虚拟地址空间 。void * ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)入口: phys_addr:要映射的起始的IO地址;size:要映射的空间的大小;flags:要映射的IO空间的和权限有关的标志;phys_addr:是要映射的物理地址;size:是要映射的长度,单位是字节
b.函数()把外设寄存器的物理地址映射到进程的用户虚拟地址空间 。
int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long pfn, unsigned long size, pgprot_t prot);int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long pfn, unsigned long size, pgprot_t prot);remap_pfn_range和io_remap_pfn_range负责为一段物理地址建立新的页表,他们的原型如下函数的返回值是0或者是个负的错误码 。
第一个函数是在pfn指向实际的RAM的时候使用,后面一个函数实在指向I/O内存时候使用,在实际使用中,除了SPARC外,对每个体系架构这两个函数都是等价的 。大多数情况下使用第一个函数,对于有移植性的要求的驱动程序,要使用与特定情形相符的函数变种 。
该函数的功能是创建页表 。其中参数vma是内核根据用户的请求自己填写的,而参数addr表示内存映射开始处的虚拟地址,因此,该函数为addr~addr+size之间的虚拟地址构造页表 。另外,pfn(Page Fram )是虚拟地址应该映射到的物理地址的页面号,实际上就是物理地址右移位 。如果为4kb,则为12,因为等于1<
c.内核提供函数(),它用来删除函数()创建的映射 。
void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)void *ioremap(unsigned long phys_addr, unsigned long size)入口: phys_addr:要映射的起始的IO地址;size:要映射的空间的大小;flags:要映射的IO空间的和权限有关的标志;phys_addr:是要映射的物理地址size:是要映射的长度,单位是字节
3、内存映射应用编程接口实战
内存映射是在进程的虚拟地址空间中创建一个映射,可分为两种:文件映射和匿名映射 。通常把文件映射的物理页称为文件页,把匿名映射的物理页称为匿名页 。
根据修改是否对其他进程 可见和是否传递到底层文件,内存映射分为共享映射和私有映射,两个进程可以使用共享的文件映射实现共享内存 。匿名映射通常是私有映射,共享的匿名映射只可能出现在父进程和子进程之间 。