一、start_kernel启动调用
start_kernel->
- setup_arch()
- build_all_zonelists()
- mm_init()
- setup_per_cpu_pageset()
以下各函数简介。
二、setup_arch()
- e820处理相关函数,如e820_add_kernel_range()。主要是e820探测物理内存,添加到内核。
- max_pfn\max_low_pfn。根据e820探测的物理内存,确定这两个全局变量,用来确定各个zone范围。
- memblock_x86_fill()。初始化memblock内存预分配系统,两种type,memory和reserved。
- conplat_reserve_memory()。私有的大块内存预分配处理,利用memblock预留出大块内存,供cblock来管理。cblock用于内核启动后可以分配出大块内存。
- x86_init.paging.pagetable_init()=xen_pagetable_init->paging_init()->zone_size_init()。初始化各zone的范围,并且初始化zone的基本信息,如一些锁、span(present\managed)_pages等。这里确定了dma32和normalzone的范围。
三、build_all_zonelists()
这个函数将各个node的所有zone串接起来。如果local node内存不足,根据此表找到其他node申请内存。前面文章有介绍。
四、mm_init()
- mem_init()。该函数调用一个很重更要的函数free_all_bootmem()。free_all_bootmem()将现在memblock管理的内存memory并且非reserved的内存释放出来,将reserved的帧__SetPageReserved,将剩余的可用的帧调用__ClearPageReserved,这样伙伴系统在初始化时可以使用这些free的帧。还有一点,那么非reserved的帧会被统计起来,totalram_pages+= 非reserved的帧,该totalram_pages变量/proc统计会用。