memblock作为系统启动初期的内存管理系统,在系统启动后就显得不是那么灵活了。在这个时候,内核就提出了页分配器来管理物理内存。而我们在Node->Zone->Page这篇中看到的这个层次结构,就是为了页分配器做的准备。
页从哪来
一路走来,我们回顾一下内存信息是怎么收集上来的
BIOS -> e820 -> memblock
那现在就要看系统是怎么从memblock的信息中,组合成page的信息的。
众所周知,在内核中我们使用page结构体来表示物理页。在SPARSEMEM这篇中我们也对page结构体的存储位置做了探索。那在最开始的时候,这个结构体是空的。那什么时候系统把物理实际存在的页面和这个page结构体对应上呢?系统是什么时候确认系统到底是有那些page可以使用的呢?如何把page结构体保存到相应的Zone结构体中的呢?
这个过程就在free_all_bootmem()函数中。
start_kernel()
mm_init()
mem_init()
free_all_bootmem()
在这个过程中你可以看到熟悉的for_each_free_mem_range()。对了,这就是遍历memory_block的内存信息,来填充page结构体的过程了。
释放
通常我们都是先讲分配,再讲释放的。但是这次要到过来。为什么呢,因为在free_all_bootmem()中就是调用了内存释放的方法来初始化page结构的。所以还是先来看看释放吧。
我们通常使用的函数是free_pages()。但是最后都调用到了函数__free_one_page()。这个函数其实比较简单,就是算的东西稍微有点绕。我们都知道页分配器中使用的是伙伴系统,也就是相邻的两个页是一对儿。所以在释放的时候,会去判断自己的伙伴是不是也是空闲