启动过程中,内核先后使用的内存分配器有:early_res,bootmem,zone allocator;后一个内存分配器启用之后,前一个内存分配器不再使用。
early_res是内存最早使用的内存分配器
arch/x86/kernel/e820.c:
1 /*
2 * Handle the memory map.
3 * The functions here do the job until bootmem takes over.
内核获取内存信息
1、实模式下用BIOS提供的中断服务获取物理内存信息,并保存在boot_params的e820_map字段中。
2、将实模式下的boot_params复制到保护模式的boot_params中
3、预留内存段信息存放到early_res中,最多20个
4、将boot_params的e820_map值复制到e820中
5、bootmem初始化,标记所有内存为已使用
6、bootmem从e820_map中取得可用内存,注册到bootmem中
7、bootmem将出现在early_res预留内存段的内存标记为已使用
1、实模式下获取BIOS提供的物理内存信息
boot/header.S->main->detect_memory->detect_memory_e820
调用BIOS提供的0x15中断服务获取物理内存信息
2、实模式boot_params复制到保护模式boot_params中
获取实模式数据过程:
a、切换保护模式,boot/header.S->main.c->pmjump.S
b、内核解压,boot/compressed/head_32.S
c、参数复制,kernel/head_32.S
跳转到压缩内核时传递的参数boot_params放在esi中,而esi在解压过程中不变,从而传给解压后内核的启动函数startup_32;
arch/x86/kernel/head_32.S:
110 /*
111 * Copy bootup parameters out of the way.
112 * Note: %esi still has the pointer to the real-mode data.
113 * With the kexec as boot loader, parameter segment might be loaded beyond
114 * kernel image and might not even be addressable by early boot page tables.
115 * (kexec on panic case). Hence copy out the parameters before initializing
116 * page tables.
117 */
118 movl $pa(boot_params),%edi
119 movl $(PARAM_SIZE/4),%ecx
120 cld
121 rep
3、预留内存区间
内核在未启动bootmem之前,使用early_res存放预留内存区间;在bootmem启动时将预留区间注入到bootmem中。
early_res分配内存主要有:内核代码数据、页表、BOOTMAP(bootmem中使用的位图)等
arch/x86/kernel/head32.c:
34 reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
4、e820取出boot_params中e820map数据
start_kernel->setup_arch->setup_memory_map
dmesg | less
BIOS-provided physical RAM map:
BIOS-e820: 0000000000000000 - 000000000009f800 (usable)
BIOS-e820: 000000000009f800 - 00000000000a0000 (reserved)
BIOS-e820: 00000000000ca000 - 00000000000cc000 (reserved)
BIOS-e820: 00000000000dc000 - 0000000000100000 (reserved)
BIOS-e820: 0000000000100000 - 000000007fef0000 (usable)
BIOS-e820: 000000007fef0000 - 000000007feff000 (ACPI data)
BIOS-e820: 000000007feff000 - 000000007ff00000 (ACPI NVS)
BIOS-e820: 000000007ff00000 - 0000000080000000 (usable)
BIOS-e820: 00000000e0000000 - 00000000f0000000 (reserved)
BIOS-e820: 00000000fec00000 - 00000000fec10000 (reserved)
BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved)
BIOS-e820: 00000000fffe0000 - 0000000100000000 (reserved)
5、bootmem初始化
start_kernel->setup_arch->initmem_init
6、bootmem注册可用内存
a、将e820中可用内存放入active_regions中(start_kernel->setup_arch->initmem_init->e820_register_active_regions)
b、将active_regions中的可用内存释放到bootmem中(start_kernel->setup_arch->initmem_init->setup_bootmem_allocator->setup_node_bootmem->free_b