1,Linux内核内存管理基础:
1》Linux系统5种地址类型:用户空间虚拟地址,物理地址,总线地址,内核逻辑地址,内核虚拟地址;
内核逻辑地址就是内核虚拟地址,内核逻辑地址通过kmalloc(标志GFP_KERNEL)分配,内核虚拟地址不一定是内核逻辑地址;
内核逻辑地址和物理地址是线性关系,之间相差固定的值;
内核逻辑地址位宽和cpu地址总线位宽一致,所以逻辑地址能够映射的物理内存大小有限,在32位架构上不到1G;
2》物理层:物理地址,页帧,低端内存,高端内存
物理地址——cpu地址总线向存储控制器传输的地址;
页帧——物理内存空间通常被划分为大小相同的页的方式来管理,每一个页面称为页帧,通常一个页帧为4K,页帧是内存地址映射的基本单位;
低端内存——内核逻辑地址构成低端内存,内核逻辑地址构成内核逻辑内存空间即就是内核常规内存空间,即就是低端内存;
高端内存——由于内核逻辑地址位宽和cpu地址总线位宽一致,所以内核逻辑地址的寻址空间有限,满足不了大内存的需求,所以就出现了高端内存,
高端内存映射内核真正的虚拟地址空间;
低端内存与高端内存的真正区别:
能够映射到内核逻辑地址空间的内存为低端内存,内核本身的数据必须存放在低端内存中;
不能够映射到内核逻辑地址空间的内存为高端内存,为用户空间进程预留内存空间;
3》数据结构:
struct page: 由于内核逻辑地址方式满足不了大内存即高端内存的映射需求,由于高端内存不能够映射到内核逻辑地址空间;所以就出现了内核内存管理子系统最重要的数据结构之一struct page,该数据结构记录了内核需要的每一个物理页帧的所有的信息,用get_free_pages()来获取空闲的page(物理页帧);
struct vm_area_struct :虚拟内存数据结构,内核内存管理子系统用该重量级数据结构表示每一个虚拟内存区域;
成员属性:unsigned long vm_start;unsigned long vm_end;unsigned long vm_pgoff;int prot,int flags,struct vm_operations_struct v_ops;
struct vm_area_struct:对虚拟内存进行操作;
成员属性:int (*open)(struct file *,struct vm_area_struct *);
int (*close)(struct file *,struct vm_area_struct *);
int (*fault)(struct vm_area_struct *,struct vm_mf *);
struct mm_struct :内存映射数据结构,记录了每一个用户空间进程的所有的内存信息,把上述数据结构都映射到一块,统一组织管理,每一个用户空间进程task_struct 实例对象都有一个mm_struct实例对象;
4》内存映射操作——系统调用mmap():
a,api:用户空间api:int mmap(void *addr,unsigned long len,unsigned long loff,int prot,int flags,unsigned long fd);
驱动模块函数:int mmap(struct file *filp,struct vm_area_struct *vma);
b,设备内存映射到用户虚拟内存空间:
两种实现方式:
c,用户空间虚拟地址直接映射到RAM上,本质上是用户空间虚拟地址直接映射到内核虚拟地址空间,包含两部分:用户空间虚拟地址映射到内核逻辑地址空间映射的物理内存上,用户空间虚拟地址映射到内核真正的虚拟地址映射的内存上;
一》用户空间虚拟地址直接映射到内核逻辑地址空间对应的内存空间上:
二》用户空间虚拟地址直接映射到内核真正的虚拟地址空间对应的内存上: