1.Linux内存模型
前面已经分析把物理内存添加到memblock以及给物理内存建立页表映射,这里我们分析sparse内存模型
在linux内核中支持3中内存模型,分别是flat memory model,Discontiguous memory model和sparse memory model。所谓memory model,其实就是从cpu的角度看,其物理内存的分布情况,在linux kernel中,使用什么的方式来管理这些物理内存
sparse内存框架图
2 sparse初始化分析
函数调用关系:start_kernel->setup_arch->paging_init->bootmem_init->sparse_init
主要是给每个section分配一个pageblock bitmap位图
每个section又可以分为若干个pageblock,每个pageblock的状态占4bit,所以一个section的pageblock bitmap大小为:
unsigned long usemap_size(void)
{
unsigned long size_bytes;
size_bytes = roundup(SECTION_BLOCKFLAGS_BITS, 8) / 8;
size_bytes = roundup(size_bytes, sizeof(unsigned long));
return size_bytes;
}
其中SECTION_BLOCKFLAGS_BITS表示一个section中的pageblock bit数量
#define SECTION_BLOCKFLAGS_BITS \
((1UL << (PFN_SECTION_SHIFT - pageblock_order)) * NR_PAGEBLOCK_BITS)
NR_PAGEBLOCK_BITS值为4,pageblock_order值为10
void __init sparse_init(void)
{
unsigned long pnum;
struct page *map;
unsigned long *usemap;
unsigned long **usemap_map;
int size;
size = sizeof(unsigned long *) * NR_MEM_SECTIONS;
/*为每个section分配一个内存,用户保存bitmap内存地址 */
usemap_map = memblock_virt_alloc(size, 0);
if (!usemap_map)
panic("can not allocate usemap_map\n");
/*分配section的pageblock bitmap位图内存 */
alloc_usemap_and_memmap(sparse_early_usemaps_alloc_node,(void *)usemap_map);
for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
if (!present_section_nr(pnum))
continue;
usemap = usemap_map[pnum];
if (!usemap)
continue;
/*映射page虚拟地址???? */
map = sparse_early_mem_map_alloc(pnum);
if (!map)
continue;
/*标记section为map状态 */
sparse_init_one_section(__nr_to_section(pnum), pnum, map,usemap);
}
memblock_free_early(__pa(usemap_map), size);
}
section的初始化
static int __meminit sparse_init_one_section(struct mem_section *ms,
unsigned long pnum, struct page *mem_map,
unsigned long *pageblock_bitmap)
{
if (!present_section(ms))
return -EINVAL;
ms->section_mem_map &= ~SECTION_MAP_MASK;
/*标记section为map状态 */
ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum) |
SECTION_HAS_MEM_MAP;
/*section的bitmap */
ms->pageblock_flags = pageblock_bitmap;
return 1;
}