1. 程式人生 > >Linux記憶體初始化之sparse記憶體模型(二)

Linux記憶體初始化之sparse記憶體模型(二)

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;
}