mem_map 分析
文章目录mem_map的作用mem_map的定义dump_stack的输出alloc_node_mem_map源码分析mem_map的作用mem_map的定义/* \linux\mm\memory.c */#ifndef CONFIG_NEED_MULTIPLE_NODES/* use the per-pgdat data instead for discontigmem - mbli...
·
mem_map的作用
mem_map是一个数组,存放了所有的页描述符。一个页对应一个页描述符。
mem_map的定义
/* \linux\mm\memory.c */
#ifndef CONFIG_NEED_MULTIPLE_NODES
/* use the per-pgdat data instead for discontigmem - mbligh */
unsigned long max_mapnr;
struct page *mem_map;
EXPORT_SYMBOL(max_mapnr);
EXPORT_SYMBOL(mem_map);
#endif
dump_stack的输出
[ 0.000000] [alloc_node_mem_map 5920] .
[ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.9.51-1.2 #136
[ 0.000000] Hardware name: Broadcom STB (Flattened Device Tree)
[ 0.000000] [<c0210710>] (unwind_backtrace) from [<c020bb54>] (show_stack+0x10/0x14)
[ 0.000000] [<c020bb54>] (show_stack) from [<c04fc93c>] (dump_stack+0x84/0x98)
[ 0.000000] [<c04fc93c>] (dump_stack) from [<c09b6e4c>] (alloc_node_mem_map.constprop.8+0x28/0xd0)
[ 0.000000] [<c09b6e4c>] (alloc_node_mem_map.constprop.8) from [<c0e0f10c>] (free_area_init_node+0xf0/0x38c)
[ 0.000000] [<c0e0f10c>] (free_area_init_node) from [<c0e065f8>] (bootmem_init+0x16c/0x1b0)
[ 0.000000] [<c0e065f8>] (bootmem_init) from [<c0e08ac0>] (paging_init+0xd28/0xd90)
[ 0.000000] [<c0e08ac0>] (paging_init) from [<c0e0429c>] (setup_arch+0x61c/0xc24)
[ 0.000000] [<c0e0429c>] (setup_arch) from [<c0e009d0>] (start_kernel+0xb8/0x404)
[ 0.000000] [<c0e009d0>] (start_kernel) from [<00008090>] (0x8090)
/*
代码调用流程:
start_kernel --> setup_arch --> paging_init --> bootmem_init --> free_area_init_node --> alloc_node_mem_map
由代码调用流程可以看出,mem_map的初始化,是在初始化node时做的。也就是说,mem_map是node下一级的一个概念。
*/
alloc_node_mem_map源码分析
/* \linux\mm\page_alloc.c */
static void __ref alloc_node_mem_map(struct pglist_data *pgdat)
{
unsigned long __maybe_unused start = 0;
unsigned long __maybe_unused offset = 0;
/* 空节点判断 */
/* Skip empty nodes */
if (!pgdat->node_spanned_pages)
return;
#ifdef CONFIG_FLAT_NODE_MEM_MAP
/* start 是起始页帧号 */
start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1);
offset = pgdat->node_start_pfn - start;
/* ia64 gets its own node_mem_map, before this, without bootmem */
/* 如果当前node没有分配node_mem_map, 则分配 */
if (!pgdat->node_mem_map) {
unsigned long size, end;
struct page *map;
/*
* The zone's endpoints aren't required to be MAX_ORDER
* aligned but the node_mem_map endpoints must be in order
* for the buddy allocator to function correctly.
*/
/* end 是终点页帧号 */
end = pgdat_end_pfn(pgdat);
end = ALIGN(end, MAX_ORDER_NR_PAGES);
// (end - start)计算当前节点有多少个page
size = (end - start) * sizeof(struct page);
map = alloc_remap(pgdat->node_id, size);
if (!map)
map = memblock_virt_alloc_node_nopanic(size,
pgdat->node_id);
pgdat->node_mem_map = map + offset;
}
#ifndef CONFIG_NEED_MULTIPLE_NODES
/*
* With no DISCONTIG, the global mem_map is just set as node 0's
*/
if (pgdat == NODE_DATA(0)) {
/* 当前节点是0号节点, 则初始化mem_map*/
mem_map = NODE_DATA(0)->node_mem_map;
#if defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) || defined(CONFIG_FLATMEM)
if (page_to_pfn(mem_map) != pgdat->node_start_pfn){
mem_map -= offset;
}
#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
}
#endif
#endif /* CONFIG_FLAT_NODE_MEM_MAP */
}
/*
这个函数只是给mem_map分配了内存空间,并没有初始化里面的数据
*/
更多推荐
已为社区贡献1条内容
所有评论(0)