Linux内存管理之mem_map对象
linux-dash
A beautiful web dashboard for Linux
项目地址:https://gitcode.com/gh_mirrors/li/linux-dash
免费下载资源
·
在linux内核中,所有的物理内存都用struct page结构来描述,这些对象以数组形式存放,而这个数组的地址就是mem_map。内核以节点node为单位,每个node下的物理内存统一管理,也就是说在表示内存node的描述类型struct pglist_data中,有node_mem_map这个成员,其针对平坦型内存 进行描述(CONFIG_FLAT_NODE_MEM_MAP),与此相反的是SPARSEMEM,其稀疏性内存描述。
也就是说,每个内存节点node下,成员node_mem_map是此node下所有内存以struct page描述后,所有这些对象的基地址,这些对象以数组形式存放。
如果系统只有一个pglist_data对象,那么此对象下的node_mem_map即为全局对象mem_map。函数alloc_node_mem_map()就是针对节点node的node_mem_map处理
此函数实现如下:
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 */ 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 = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1); 起始地址必须对其,这个一般按照MB级别对齐即可。 offset = pgdat->node_start_pfn - start; 看看偏移地址,对齐后地址与真正开始地址之间的偏移大小
如果pgdat目前没有设置node_mem_map则对其设置 /* ia64 gets its own node_mem_map, before this, without bootmem */ 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 = pgdat_end_pfn(pgdat);获取节点内结束页帧号pfn end = ALIGN(end, MAX_ORDER_NR_PAGES);考虑对齐影响,注意这个需要向前舍入。
size = (end - start) * sizeof(struct page);计算需要的数组大小,需要注意end-start是页帧个数,每个页需要一个struct page对象,
所以,这里是乘关系,这样得到整个node内所有以page为单位描述需要占据的内存。
下面分配这个内存大小 map = alloc_remap(pgdat->node_id, size); if (!map) 如果这里分配失败,则通过memblock管理算法分配内存。 map = memblock_virt_alloc_node_nopanic(size, pgdat->node_id);
这里我们可以计算一下,假如4GB内存,则总共有4GB/page_size 个页帧,页大小假如为4KB,则总共有2^20个页,每个页32字节,则这些页占据内存为
2^20 * 32 = 2^25 = 32MB,可以看到,仅仅用于struct page描述的就占据了32MB,32MB/4GB=7.8125%,从占用率来看,这个数据还好。
这里对最终的node_mem_map修正偏移位置。一般这个offset为0.
pgdat->node_mem_map = map + offset; }
下面是对全局对象mem_map设置,其在当前只有一个node节点时设置。直接来自node 0的node_mem_map值。
#ifndef CONFIG_NEED_MULTIPLE_NODES /* * With no DISCONTIG, the global mem_map is just set as node 0's */ if (pgdat == NODE_DATA(0)) { 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 */ }
GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e
added ecosystem file for PM2 4 年前
5def40a3
Add host customization support for the NodeJS version 4 年前
更多推荐
已为社区贡献7条内容
所有评论(0)