默认为3.9.1版本内核
为什么要从这个函数开始?个人习惯吧,我比较懒,就从内核初始化入口开始。
-----------------------------------------------------------------------------------------------------
先看一张图,start_kernel函数调用关系图:
为啥要看这个?我想知道谁掉用了它!挨个看一下比较好~
void __init x86_64_start_reservations(char *real_mode_data) { /* version is always not zero if it is copied */ if (!boot_params.hdr.version) copy_bootdata(__va(real_mode_data));//复制bootdata? reserve_ebda_region();//预留dbda区域? start_kernel(); }
void __init x86_64_start_kernel(char * real_mode_data) { int i; /* * Build-time sanity checks on the kernel image and module * area mappings. (these are purely build-time and produce no code) */ BUILD_BUG_ON(MODULES_VADDR < KERNEL_IMAGE_START); BUILD_BUG_ON(MODULES_VADDR-KERNEL_IMAGE_START < KERNEL_IMAGE_SIZE); BUILD_BUG_ON(MODULES_LEN + KERNEL_IMAGE_SIZE > 2*PUD_SIZE); BUILD_BUG_ON((KERNEL_IMAGE_START & ~PMD_MASK) != 0); BUILD_BUG_ON((MODULES_VADDR & ~PMD_MASK) != 0); BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL)); BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) == (__START_KERNEL & PGDIR_MASK))); BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END); /* Kill off the identity-map trampoline */ reset_early_page_tables(); /* clear bss before set_intr_gate with early_idt_handler */ clear_bss(); for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) set_intr_gate(i, &early_idt_handlers[i]); load_idt((const struct desc_ptr *)&idt_descr); copy_bootdata(__va(real_mode_data)); /* * Load microcode early on BSP. */ load_ucode_bsp(); if (console_loglevel == 10) early_printk("Kernel alive\n"); clear_page(init_level4_pgt); /* set init_level4_pgt kernel high mapping*/ init_level4_pgt[511] = early_level4_pgt[511]; x86_64_start_reservations(real_mode_data); }
信息量太大了,好吧,我承认我看不懂。。。等我能看懂了再来更新之。
下面直接看start_kernel函数:
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern const struct kernel_param __start___param[], __stop___param[];
/*
* Need to run as early as possible, to initialize the
* lockdep hash:
*/
lockdep_init();/*内核调试模块,用于检查内核互斥机制潜在的死锁问题*/
smp_setup_processor_id();/* 指定当前的cpu的逻辑号,这个函数对应于对称多处理器的设置,当系统中只有一个cpu的情况,此函数为空,什么也不做 */
debug_objects_early_init();
/*
* Set up the the initial canary ASAP:
*/
boot_init_stack_canary();/*初始化栈canary值,canary值用于防止栈溢出攻击的堆栈的保护字*/
cgroup_init_early();/*一组进程的行为控制,做数据结构和其中链表的初始化*/
local_irq_disable();/*关闭当前CUP中断*/
early_boot_irqs_disabled = true;
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
tick_init();/*初始化内核时钟系统*/
boot_cpu_init();/*激活当前CPU*/
page_address_init();/*高端内存相关,未定义的话为空函数*/
printk(KERN_NOTICE "%s", linux_banner);
setup_arch(&command_line);/*内核架构相关初始化函数*/
mm_init_owner(&init_mm, &init_task);/*初始化init_mm结构体*/
mm_init_cpumask(&init_mm);
setup_command_line(command_line);/*对command_line进行备份与保存*/
setup_nr_cpu_ids();/*以下三个函数针对SMP处理器,不是SMP处理器都为空函数*/
setup_per_cpu_areas();
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
build_all_zonelists(NULL, NULL);/*设置内存相关节点和其中的内存域数据结构*/
page_alloc_init();
/*打印与解析内核启动参数*/
printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
-1, -1, &unknown_bootoption);
jump_label_init();
/*
* These use large bootmem allocations and must precede
* kmem_cache_init()
*/
setup_log_buf(0);/*使用bootmem分配一个启动信息的缓冲区*/
pidhash_init();/*使用bootmem分配并初始化PID散列表*/
vfs_caches_init_early();/*前期VFS缓存初始化*/
sort_main_extable();/*对内核异常表进行排序*/
trap_init();/*对内核陷阱异常经行初始化,ARM架构中位空函数*/
mm_init();/*初始化内核内存分配器,启动信息中的内存信息来自此函数中的mem_init函数*/
/*
* Set up the scheduler prior starting any interrupts (such as the
* timer interrupt). Full topology setup happens at smp_init()
* time - but meanwhile we still have a functioning scheduler.
*/
sched_init();/*初始化调度器数据结构并创建运行队列*/
/*
* Disable preemption - early bootup scheduling is extremely
* fragile until we cpu_idle() for the first time.
*/
preempt_disable();/*禁用抢占和中断,早期启动时期,调度是极其脆弱的*/
if (!irqs_disabled()) {
printk(KERN_WARNING "start_kernel(): bug: interrupts were "
"enabled *very* early, fixing it\n");
local_irq_disable();
}
idr_init_cache();/*为IDR机制分配缓存*/
perf_event_init();/*CPU性能检测机制初始化*/
rcu_init();/*内核RCU机制初始化*/
radix_tree_init();/*内核radix树算法初始化*/
/* init some links before init_ISA_irqs() */
early_irq_init();/*前期外部中断描述符初始化*/
init_IRQ();/*架构相关中断初始化*/
init_timers();/*以下5个函数是软中断和内核时钟机制初始化*/
hrtimers_init();
softirq_init();
timekeeping_init();
time_init();
profile_init();/*profile子系统初始化,内核的性能调试工具*/
call_function_init();
if (!irqs_disabled())
printk(KERN_CRIT "start_kernel(): bug: interrupts were "
"enabled early\n");
early_boot_irqs_disabled = false;
local_irq_enable();/*开启总中断*/
kmem_cache_init_late();/*slab分配器后期初始化*/
/*
* HACK ALERT! This is early. We're enabling the console before
* we've done PCI setups etc, and console_init() must be aware of
* this. But we do want output early, in case something goes wrong.
*/
console_init();/*初始化控制台*/
if (panic_later)/*检查内核恐慌标准,如果有问题,打印信息*/
panic(panic_later, panic_param);
lockdep_info();/*打印lockdep调试模块信息*/
/*
* Need to run this when irqs are enabled, because it wants
* to self-test [hard/soft]-irqs on/off lock inversion bugs
* too:
*/
locking_selftest();
/*检查initrd的位置是否符合要求*/
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && !initrd_below_start_ok &&
page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
"disabling it.\n",
page_to_pfn(virt_to_page((void *)initrd_start)),
min_low_pfn);
initrd_start = 0;
}
#endif
page_cgroup_init();
debug_objects_mem_init();
kmemleak_init();/*内存泄露检测机制的初始化*/
setup_per_cpu_pageset();/*设置每个CPU的页组并初始化*/
numa_policy_init();/*分一致性内存访问(NUMA)初始化*/
if (late_time_init)
late_time_init();
sched_clock_init();/*初始化调度时钟*/
calibrate_delay();
pidmap_init();/*PID分配映射初始化*/
anon_vma_init();
#ifdef CONFIG_X86
if (efi_enabled(EFI_RUNTIME_SERVICES))
efi_enter_virtual_mode();
#endif
thread_info_cache_init();
cred_init();/*任务信用系统初始化*/
fork_init(totalram_pages);/*进程创建机制初始化*/
proc_caches_init();/*进程caches初始化*/
buffer_init();/*缓存系统初始化,创建缓存头空间,并检查其大小限制*/
key_init();/*内核密钥管理系统初始化*/
security_init();/*内核安全框架初始化*/
dbg_late_init();/*内核调试系统后期初始化*/
vfs_caches_init(totalram_pages);/*虚拟文件系统缓存初始化*/
signals_init();/*信号管理系统初始化*/
/* rootfs populating might need page-writeback */
page_writeback_init();/*页回写机制初始化*/
#ifdef CONFIG_PROC_FS
proc_root_init();/*proc文件系统初始化*/
#endif
cgroup_init();/*control group正式初始化*/
cpuset_init();/*CPUSET初始化*/
taskstats_init_early();/*任务状态早期初始化函数,为任务获取高速缓存并初始化互斥机制*/
delayacct_init();/*任务延迟机制初始化*/
check_bugs();
acpi_early_init(); /* before LAPIC and SMP init */
sfi_init_late();
if (efi_enabled(EFI_RUNTIME_SERVICES)) {
efi_late_init();
efi_free_boot_services();
}
ftrace_init();
/* Do the rest non-__init'ed, we're now alive */
rest_init();
}