调用流程如下
kern_init --> pmm_init-->page_init-->init_memmap--> pmm_manager->init_memmap
从page_init 说起
先找到 e820map 这个数据结构 读取BISO 设置好的可用内存空间
将空闲内存的最后一个地址分配给 maxpa
如果maxpa 最大为 KMEMSIZE
npage= maxpa / PGSIZE 计算总共的页数量
end 作为kernel 的结束 向高位 对其 PGSIZE
作为 pages的起始地址
从pages 开始向后 分配 npage 个空闲的端 进行 SetPageReserved
freemem 就等于 pages+npage*sizeof(page) 进行 PADDR 后的到 实际的物理地址起始的空闲内存地址
换句话说 就是pages 仍然存贮逻辑地址
对于每一个空闲的内存块, 开始地址最小不能小于 freemem 最大不能大于 KMEMSIZE(考虑到从0开始?)
将 begin 和 end 分别向上向下 与 PGSIZE 对其
执行 init_memmap(pa2page(begin),(end-begin)/PGSIZE)
pa2page 取出物理的前22位当作索引 到pages[ppn(pa)] 取出对应的页表首地址
而其中的 init_memmap 接受一个 Page*base size_t n
调用pagememger - initmap 方法对页表条目进行初始化
下面我们看一个 default_meminit 的行为
初始化 从Base 开始的 n个页表条目
首先
assert(PageRserved(p)) 认为我要初始化的页表是可以初始化的 前面进行过初始化了(这里是确认?)
p->flags = p-> property=0 设置pages 相关属性
set_page_ref(p,0) 清零引用
nr_free +=n 多出来了n 个可用的内存空间?
base-> property = n 这个用于 first_fit 策略
SetPageProperty(base)
init_pmm_manager 是 指定了 使用的内存分配器位default
初始化过后的内存情况
default_alloc_pages
接受一个 参数size_t n 需要分配的页数
if(n > nr_free){
return NULL;// 如果当前的空余页数 已经不够了 就返回NULL
}
阅读注释
首先了解 list list.h 中的接口
使用 list_init list_add list_add_before list_del list_next list_prv
tricky method that is to transform a genera list struct to special struct
le2page
(2):
default 可是重用提供的 defalut_init
并且设置 nr_free =0
default_init_memmap :
设置page 的property 位,这意味这个page 是有效的
p->property 如果是首个空闲页的话 设置为空闲位的总大小 ,否则设置为0
p->ref 如果等于0 那么就说明 p 是free 的了
我们可以使用 p->page_link 将一个页插入 free_list 中,
list_add_before(&free_list,&(p->page_link)); 插入一整块的时候需要进行 nr_free+=n
efault_alloc_pages:
default_free_pages 的逻辑
接受一个基址 一个size_t n
循环n个pages 对于每一个Pages 要注意的是不一定是 分配时候的哪一个 首页
断言 PageProperty 与 Reservered 字段都是 0 (保证不会释放 未分配的空间)
清空 flag ref 字段 为0
设置这个 base 的property = n
setpropert
遍历整个free_list 找到和这个段相邻的其他段 进行合并(具体来说就是 前相连和后相连)
然后要找到正确的位置插入经过合并的内存页段