深入理解Linux内核-第八章内存管理

页框管理:页描述符:描述页框的状态,所有的页描述符存储在mem_map数组中。每个描述符长度为32字节

内存区管理:(X86结构为例)

zone_DMA:包含低于16MB的内存页框【ISA总线直接内存存取的限制】

zone_NORAML:包含16MB--896MB的内存页框

zone_HIGHMEM:高于896MB的内存页框。

zone_DMA和zone_NORAML包含的常规内存,通过线性地址直接映射到线性地址空间的第四个GB。

 

当内存有足够多的的空闲时,内存分配被立刻满足,但是当空间不够时,内存分配被阻塞,必须收回一些内存。

保留的页框池:内核为原子内存分配请求保留一个页框池,只有在内存不足时才使用。保留内存的数量存放在min_free_kbytes变量中。ZONE_DMA和ZONE_NORMAL都保留一定数量的页框给保留内存。原子内存请求不应当被阻塞,这种情况发生在:临界区或者中断代码的时候。(GFP_ATMOTIC标志)

 

分区页框分配器:处理对连续页框组的内存分配请求。当请求分配时,搜索一个满足要求的管理区,在管理区内使用伙伴系统分配页框。为了达到更好的性能,小部分页框被保留在高速缓存中(slab?),用于快速的对单个页框的分配请求。

alloc_pages(gfp_mask, order);//分配2^order个页框,返回第一个页框描述符的地址。
alloc_page(gfp_mask);//分配单个页框,返回该页框描述符的地址。

__get_free_pages(gfp_mask, order);//分配2^order个页框,返回第一个页框的线性地址。
__get_free_page(gfp_mask);//分配单个页框,返回该页框的地址。

每CPU页框高速缓存:使用提前分配好的页框。页框的信息保存在内存描述符内。

高端内存页框的内核映射:内核不能直接访问高端内存的页框,没有相应的线性地址。内核线性地址空间的最后128MB用于高端内存的映射,这种映射是暂时的,通过重复使用,使得内核在不同时间能够访问整个高端内存。

永久内核映射:建立永久内核映射可能阻塞当前进程,这发生在空闲页表项不存在时,也就是在高端内存上没有页表项可以用作页框的窗口。因此不能用在中断处理程序和延迟函数中。不使用的映射需要kunmap()。【永久:一个控制路径使用,可以被阻塞,因为可以长期占有该映射窗口,直到释放此窗口】

这些用于永久内核映射的窗口,位于主内核页表的一个专门的页表中(应该是一个页表项对应的页表),因此内核一次最多访问2MB或者4MB的高端内存。(取决于是否开启PAE)

临时内核映射:每个CPU都有它自己的13个窗口的集合,一个窗口表示一个页表项,映射一个页框。内核必须确保同一窗口不会被两个不同的控制路径使用。【临时:每次直接用,直接覆盖上一次的映射,这意味着内核控制路径不能阻塞,否则可能被其他控制路径使用相同的映射窗口,导致之前的映射失效,但是还要使用】

  1. 内核在 FIXADDR_START 到 FIXADDR_TOP 之间保留了一些线性空间用于特殊需求。这个空间称为”固定映射空间”。在这个空间中有一部分用于高端内存的临时映射
  2. 这块空间具有如下特点:

(1)每个 CPU 占用一块空间

(2)在每个 CPU 占用的那块空间中,又分为多个小空间,每个小空间大小是 1 个 page,每个小空间用于一个目的,这些目的定义在 kmap_types.h 中的 km_type 中。

 

伙伴系统算法:解决外碎片问题,即提供连续的页框。每个管理区都有不同的伙伴算法。

管理区分配器:1)应当保护保留的页框池(用于原子内存分配);2)内存不足且允许阻塞当前进程时,应当触发页框回收算法,回收后再次尝试分配;3)尽量不分配DMA区的页框。

内存区管理:(内存区:具有连续的物理地址,任意长度的内存)内碎片产生的主要原因:请求的内存大小和分配的内存大小不匹配。【页内碎片

 

slab分配器:

  • 基本前提:
  1. 所存放的数据类型可以影响内存区的分配方式
  2. 内核函数倾向于反复请求同一种类型的内存区
  3. 内存区的请求可以根据他们发生的频率来分类  等

slab分配器主要是针对那些内核中小内存但是多而频繁的内存需求的申请和释放的特征入手,做的局部物理页的优化策略,提高效率降低分配时间,还是空间换时间。

  • 普通高速缓存:
  1. 第一个高速缓存kmem_cache,包含由内核使用的其余高速缓存的高速缓存描述符。也就是存放高速缓存描述符对象的高速缓存。
  2. 普通用途的高速缓存,系统初始化期间调用,每种大小包含两个高速缓存,分别存放在DMA和常规内存中。用于kmalloc函数申请内存。
  • 专用高速缓存:

由kmem_cache_creat()创建,步骤:申请一个高速缓存描述符,保存在第一个普通高速缓存cache_cache中。

  • slab着色:

  • 内存池

 

非连续内存分配:

把内存映射到一个连续的页框可以充分利用高速缓存,获得较低的访问时间。如果对内存区的请求不是很频繁,那么通过连续的线性地址来访问非连续的页框,可以避免外碎片,缺点是必须打乱内核页表

非连续内存分配(vmalloc(unsigned long size)函数)步骤:

  1. 调用get_vm_area()函数,在线性地址VMALLOC_START到VMALLOC_END之间查找一个空闲的内存区,size+4K的大小,取页面整数个。
  2. 并分配和初始化一个vm_struct描述符
  3. 请求一组连续的内存区,用于保存映射的非连续的物理页面的页描述符的指针数组。
  4. 修改内核页表,为已经分配的线性区和分配的物理页面建立映射。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值