linux内核学习1 start_kernel()

来源:互联网 发布:旋转矩阵计算器 编辑:程序博客网 时间:2024/06/06 13:05

默认为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_INITRDif (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;}#endifpage_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_X86if (efi_enabled(EFI_RUNTIME_SERVICES))efi_enter_virtual_mode();#endifthread_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_FSproc_root_init();/*proc文件系统初始化*/#endifcgroup_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();}

参考文章:http://blog.chinaunix.net/uid-20746260-id-3176497.html