我最近正在深入研究Linux内存管理的细节,因为我想为自己的玩具内核实现类似的东西,所以我希望熟悉细节的人能帮助我理解一件事。显然,物理内存管理器是伙伴算法,它进一步专门用于返回特定顺序的页面块(0到9,其中0只是一个页面)。对于每个订单,块都存储为链接列表。假设如果请求了一个5阶块但在5阶块列表中找不到,则该算法按顺序搜索一个块,将其分成两部分,给出所请求的一半并将另一半的顺序移动到较低的位置(如它的大小只有一半)。 我没有得到的是内核如何存储这些结构,或者它如何为它们分配空间。因为对于订单0页面,您需要1M条目(每个是4KiB页面),这是否意味着内核分配1MiB * sizeof(结构页面)?订单1及以上的块怎么样?内核是否通过将它们标记为更高的顺序来重用已分配的块,并且当它需要将其拆分为两个时,只返回块并获取一个未使用的块?
答案 0 :(得分:4)
我没有得到的是内核如何存储这些结构,或者它如何为它们分配空间。因为对于订单0页面,您需要1M条目(每个是4KiB页面),这是否意味着内核分配1MiB * sizeof(结构页面)?
通过调用paging_init()
(arch / x86 / mm / init_32.c;一些描述 - https://www.kernel.org/doc/gorman/html/understand/understand005.html 2.3区域初始化和http://repo.hackerzvoice.net/depot_madchat/ebooks/Mem_virtuelle/linux-mm/vminit.html初始化内核页表)来完成区域的初始化setup_arch()
通过(native_pagetable_init()
和间接通话1166 x86_init.paging.pagetable_init();
):
690 /*
691 * paging_init() sets up the page tables - note that the first 8MB are
692 * already mapped by head.S.
...*/
697 void __init paging_init(void)
698 {
699 pagetable_init();
...
711 zone_sizes_init();
712 }
pagetable_init()
在1024 swapper_pg_dir
的{{1}}数组中创建内核页表。
zone_sizes_init()
实际上定义了物理内存区域,并调用了free_area_init_nodes()
to initialize them free_area_init_node()
实际工作(对于每个NUMA节点pgd_t
)alloc_node_mem_map()
中调用三个函数:
for_each_online_node(nid) {...}
打印dmesg中每个节点的页数(calculate_node_totalpages()
实际工作;它们的内存由bootmem allocator doc2 free_area_init_core()
分配(您可以通过struct page
内核引导选项查看其调试): bootmem_debug=1
4936 size = (end - start) * sizeof(struct page);
4937 map = alloc_remap(pgdat->node_id, size);
struct zone
(填写http://repo.hackerzvoice.net/depot_madchat/ebooks/Mem_virtuelle/linux-mm/zonealloc.html#INITIALIZE中的位图)。在init_currently_empty_zone()
中为旧内核描述的if (!map) map = memblock_virt_alloc_node_nopanic(size, pgdat->node_id);
的功能如下:
free_area_init_core
构建内存映射,并在free_area_init_core()中初始化freelists和buddy位图。
每个区域的免费订单列表已初始化,订单被标记为没有任何免费页面:free_area_init_core()
- > zone_init_free_lists
- > start_kernel()
:
free_area_init_core()
PS:内核中有 init(),它被称为{{3}},而LXR(Linux交叉引用)将帮助您在函数之间导航(我发布了到lxr的链接) .free-electron.com,但有几个在线LXR):
4147 static void __meminit zone_init_free_lists(struct zone *zone)
4148 {
4149 unsigned int order, t;
4150 for_each_migratetype_order(order, t) {
4151 INIT_LIST_HEAD(&zone->free_area[order].free_list[t]);
4152 zone->free_area[order].nr_free = 0;
4153 }
4154 }