修改物理页面内存属性_内存管理(15)物理页面是如何加入伙伴系统的以及物理页面的释放

zone初始化完毕后,那其中对应的物理页面是如何加入到伙伴系统进行管理的呢?
相关代码文件:mm/nobootmem.cmm/page_alloc.c

__init free_low_memory_core_early函数

f315f55f9ad92479e20dc0bbd43c94a9.png

free_low_memory_core_early实现

  • for_each_free_mem_range遍历所有memblock的region,找到region的起始地址和结束地址然后传给__free_memory_core函数。在__free_memory_core函数中主要调用了__free_pages_memory函数。

__free_pages_memory函数

6787dced3ff85dddc3ac14499c1058df.png

__free_pages_memory

  • 第27行的循环以ORDER为步长来对当前region下可分配的内存进行分配。
  • 第28行主要用于计算ORDER,其中_ffs(start)函数的作用是计算start地址中第一次出现1的BIT位是第几位,比如假设start=0xA800,那么_ffs(start)得到的就是8,为什么要这么做,因为start是按页对齐的也就是0x400,而伙伴系统的物理页面是按照2^n次幂来添加的,最大的ORDER为10,也就是最大按2^10次幂页面大小分配,所以第28行就是为了计算当前起始地址下理论上最大可支持分配的物理页面阶层。
  • 理解了28行那第30行的循环就一目了然,目的是为了计算当前最大可支持的物理页面分配阶层。
  • __free_pages_bootmem函数被调用继续后面的处理在计算出order后

综上,物理页面是按2^ORDER为步长将物理页面加入到伙伴系统中的。而完成这项工作的函数主要由__free_pages_bootmem函数来完成,在其中又主要调用页面释放函数_free_pages来完成这项工作。它的核心功能就是把页面添加到伙伴系统中适当的free_area链表中,释放时会顺便查阅相邻的内存块是否也空闲,如果有空闲就合并然后添加到更高阶层的free_area链表中。


物理页面的释放

__free_pages_bootmem函数

0916ccc61aa1965565e0183bef0a87c8.png

__free_pages_bootmem

  • 在__free_pages_bootmem函数中对物理页面的释放主要看_free_pages函数

_free_pages函数

363f0fbd3094d128958ddcbc59a0f17e.png

_free_pages

  • 在_free_pages函数中分了两种情况,一种是ORDER为0时对页面的释放,它主要是针对特殊情况的页面释放。另一种就是正常情况的释放。先看正常情况

__free_pages_ok函数

1cae389c15e0644849a08168bc65170e.png

__free_pages_ok

  • 在__free_pages_ok函数中82~84行找到了并设置了页面对应的migratetype属性信息。而对物理页面的释放关键在free_one_page->__free_one_page函数。

__free_one_page

ea7bd2dc0b67120f79873fe9be98e3d9.png

__free_one_page实现1

  • 第97行计算所属pageblock的索引
  • 第98~118行循环结构就是判断在伙伴系统中是否存在与是否页面相邻的内存块,如果存在就合并为更大的内存块,将其加入更高阶层的空闲链表中。其中第99行在伙伴系统中查找是否有相邻内存块,第101行判断是否与当前待释放页面ORDER、ZONE等是否一致。如果是将其从伙伴系统的当前LRU下摘下以便和待释放页面合并到更高阶层的free_area空闲链表中。
f4b4561b33dd427dfd35676b5ec0c829.png

__free_one_page实现2

  • 第114~117行合并两个相邻的内存块,ORDER++继续寻找是否存在更大的相邻的内存块。
  • 最后134行将最终合并的内存块添加到伙伴系统对应阶层的free_area空闲链表中

正常情况的页面释放分析完毕,回到特殊情况下的页面释放,当ORDER == 0时调用free_hot_cold_page函数来释放页面。

free_hot_cold_page函数

8d21324e2ef87c1709bbd5598e63907a.png

free_hot_cold_page实现

  • 在zone中之前有讲到一个变量pageset是为每个CPU初始化一个percpu变量,151~155行就是将ORDER==0下的页面释放到这个变量对应的链表下
  • per_cpu_pages变量中high的含义如下↓,当per_cpu_pages中的页面高于high时就会调用free_pcppages_bulk函数并最终还是调用__free_one_page函数回收页面到伙伴系统中。

struct per_cpu_pages数据结构

a04e56ccf237b6ea4a2a5e15c92327f9.png

struct per_cpu_pages数据结构

  • 其中count表示在当前zone中per_cpu_pages的页面数量;high表示当缓存的页面高于high时会回收页面到伙伴系统中;batch表示一次回收到伙伴系统页面的数量

其大致的流程框架图如下:

f81d8ad859e1e43cbcf50ddf3175eaab.png

物理页面加入伙伴系统的流程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值