linux内核启动顺序

来源:互联网 发布:淘宝客优惠券cms 编辑:程序博客网 时间:2024/06/05 09:47

参见linux源码树结构

linux内核的中心是文件init/main.c。

在底层架构相关的设置完成之后立刻调用了start_kernel函数。start_kernel函数就位于init/main.c。


kernel代码执行顺序大致如下:

架构相关  ( arch / * /) ---> 函数start_kernel() (init/main.c)  ---> 函数init( init/main.c ) --->  启动用户进程init

架构相关:

         -.解压和移动内核代码本身

         -.初始化硬件(包括设置底层内存管理)

         -.把控制权交给start_kernel

start_kernel():

         -.打印内核版本信息,初始化命令行

          -.初始化终端输出设备

          -.开启中断

  -.初始化内存,调度,时钟等

         -.调用rest_init()    // 启动一个内核线程运行 init(),  进入idle循环

init():

          -.启动其他处理器(SMP机器)

          -.启动设备子系统

         -.挂载root文件系统

          -.释放不用的内核内存

          -.运行 /sbin/init 程序   也就是1号进程(用户进程),到此内核启动完成。后续各种程序有1号进程启动,像 网络服务,getty。


你可以在start_kernel() , init() 和各种模块中 添加printk()函数打印信息,帮助理解。


start_kernel()代码

asmlinkage __visible void __init start_kernel(void){char *command_line;char *after_dashes;/* * Need to run as early as possible, to initialize the * lockdep hash: */lockdep_init();set_task_stack_end_magic(&init_task);smp_setup_processor_id();debug_objects_early_init();/* * Set up the the initial canary ASAP: */boot_init_stack_canary();cgroup_init_early();local_irq_disable();early_boot_irqs_disabled = true;/* * Interrupts are still disabled. Do necessary setups, then * enable them */boot_cpu_init();page_address_init();pr_notice("%s", linux_banner);setup_arch(&command_line);mm_init_cpumask(&init_mm);setup_command_line(command_line);setup_nr_cpu_ids();setup_per_cpu_areas();smp_prepare_boot_cpu();/* arch-specific boot-cpu hooks */build_all_zonelists(NULL, NULL);page_alloc_init();pr_notice("Kernel command line: %s\n", boot_command_line);parse_early_param();after_dashes = parse_args("Booting kernel",  static_command_line, __start___param,  __stop___param - __start___param,  -1, -1, &unknown_bootoption);if (!IS_ERR_OR_NULL(after_dashes))parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,   set_init_arg);jump_label_init();/* * These use large bootmem allocations and must precede * kmem_cache_init() */setup_log_buf(0);pidhash_init();vfs_caches_init_early();sort_main_extable();trap_init();mm_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 (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n"))local_irq_disable();idr_init_cache();rcu_init();/* trace_printk() and trace points may be used after this */trace_init();context_tracking_init();radix_tree_init();/* init some links before init_ISA_irqs() */early_irq_init();init_IRQ();tick_init();rcu_init_nohz();init_timers();hrtimers_init();softirq_init();timekeeping_init();time_init();sched_clock_postinit();perf_event_init();profile_init();call_function_init();WARN(!irqs_disabled(), "Interrupts were enabled early\n");early_boot_irqs_disabled = false;local_irq_enable();kmem_cache_init_late();/* * 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("Too many boot %s vars at `%s'", panic_later,      panic_param);lockdep_info();/* * 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();#ifdef CONFIG_BLK_DEV_INITRDif (initrd_start && !initrd_below_start_ok &&    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {pr_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_ext_init();debug_objects_mem_init();kmemleak_init();setup_per_cpu_pageset();numa_policy_init();if (late_time_init)late_time_init();sched_clock_init();calibrate_delay();pidmap_init();anon_vma_init();acpi_early_init();#ifdef CONFIG_X86if (efi_enabled(EFI_RUNTIME_SERVICES))efi_enter_virtual_mode();#endif#ifdef CONFIG_X86_ESPFIX64/* Should be run before the first non-init thread is created */init_espfix_bsp();#endifthread_info_cache_init();cred_init();fork_init(totalram_pages);proc_caches_init();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();proc_root_init();nsfs_init();cgroup_init();cpuset_init();taskstats_init_early();delayacct_init();check_bugs();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();}



0 0
原创粉丝点击