Linux如何为其物理分配器分配内存?

时间:2015-03-15 01:01:08

标签: c linux memory-management linux-kernel kernel

我最近正在深入研究Linux内存管理的细节,因为我想为自己的玩具内核实现类似的东西,所以我希望熟悉细节的人能帮助我理解一件事。显然,物理内存管理器是伙伴算法,它进一步专门用于返回特定顺序的页面块(0到9,其中0只是一个页面)。对于每个订单,块都存储为链接列表。假设如果请求了一个5阶块但在5阶块列表中找不到,则该算法按顺序搜索一个块,将其分成两部分,给出所请求的一半并将另一半的顺序移动到较低的位置(如它的大小只有一半)。 我没有得到的是内核如何存储这些结构,或者它如何为它们分配空间。因为对于订单0页面,您需要1M条目(每个是4KiB页面),这是否意味着内核分配1MiB * sizeof(结构页面)?订单1及以上的块怎么样?内核是否通过将它们标记为更高的顺序来重用已分配的块,并且当它需要将其拆分为两个时,只返回块并获取一个未使用的块?

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_talloc_node_mem_map()中调用三个函数:

  • for_each_online_node(nid) {...}打印dmesg中每个节点的页数(
  • doc1为此节点中的每个物理页面分配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);

  

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 }