Linux内存管理子系统
1.Linux子系统
- Linux内核组成:SCI系统调用接口;PM进程管理子系统;MM内存管理子系统;Arch体系结构相关代码;DD驱动程序;Network Stack网络协议站;VFS虚拟文件系统;DD驱动程序。
2.Linux内存管理子系统
- 右边是虚拟地址的分配,上面是物理地址的分配,下面是虚拟地址到物理地址的转换。
- Linux支持的虚拟地址空间由硬件来决定,比如32位的处理器只支持4G的虚拟内存,4G内存又被分为用户空间(0~3G)和内核空间(3~4G),即3:1的方式分配。
- 内核空间又可分为以下四个部分:(由于各个区的映射到物理内存方式不同划分为4部分)
- a)直接映射区(3 - 3G+896M)直接映射,线性访问低端内存,较为简单,减去3G直接对应物理内存,最高达到896M
- b)vmalloc区:非线性访问高端内存
- c)永久内核映射区:固定访问高端内存
- d)固定映射线性地址区:与一些特殊寄存器固定映射地址
- 对于高端内存与低端内存的解释:
- 在物理地址中:
- (0-896M):低端内存,即对应于直接映射区
- (896-该物理地址上限):高端内存
2.2 虚拟地址转化为物理地址
- 注:cr3寄存器(页表录基地址)
- 学过操作系统的同学应该对这幅图不陌生。先把虚拟地址的高10位取出来,作为偏移加上基地址作为页目录,然后指向页表基地址。页表基地址加上中间10位就可以取到一个物理页的基地址,物理页的基地址加上后12位的页内偏移,就可以找到物理页的存储单元。
2.3 物理内存分配
- 注:----->为了避免物理地址空间的浪费,在用户空间和内核空间分配的任何地址都为虚拟地址。
- 在用户空间:当使用系统调用的函数:malloc、fork、等函数分配到虚拟内存时,只有当访问该虚拟内存时才会进行真正的物理内存分配。
- 分配得到物理内存的过程:
- 当访问分配的虚拟地址时,木有发现与之对应的物理地址,则产生请(缺)页异常。。进而去空闲页框中去请求空闲的物理内存。
- 在内核空间(两种方式):
- 1.内核程序一般使用vmalloc分配区去请求内核页表去请求物理地址,同样也会发生请(缺)页异常。
- 2.内核程序使用物理内存映射区,通过kmalloc函数使用Slap管理功能,从空闲的内存池取出空闲的物理内存。池中的内存已与一段物理内存对应好了,所以不会产生请(缺)页异常。 slap:先从空闲的内存中取出,放入自己的池中。
kmalloc()和vmalloc()介绍
- kmalloc()
- 用于申请较小的、连续的物理内存
- 1. 以字节为单位进行分配,在<linux/slab.h>中
- 2. void *kmalloc(size_t size, int flags) 分配的内存物理地址上连续,虚拟地址上自然连续
- 3. gfp_mask标志:什么时候使用哪种标志?如下:
- void kfree(const void *ptr)
- 释放由kmalloc()分配出来的内存块
- vmalloc()
- 用于申请较大的内存空间,虚拟内存是连续的
- 1. 以字节为单位进行分配,在<linux/vmalloc.h>中
- 2. void *vmalloc(unsigned long size) 分配的内存虚拟地址上连续,物理地址不连续
- 3. 一般情况下,只有硬件设备才需要物理地址连续的内存,因为硬件设备往往存在于MMU之外,根本不了解虚拟地址;但为了性能上的考虑,内核中一般使用kmalloc(),而只有在需要获得大块内存时才使用vmalloc(),例如当模块被动态加载到内核当中时,就把模块装载到由vmalloc()分配的内存上。
- 4.void vfree(void *addr),这个函数可以睡眠,因此不能从中断上下文调用。
malloc(), vmalloc()和kmalloc()区别
- kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存
- kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc不保证任何东西(这点是自己猜测的,不一定正确)
- kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大
- 内存只有在要被DMA访问的时候才需要物理上连续
- vmalloc比kmalloc要慢