Linux内核启动分析

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">Linux内核启动代码由位于init/main.cinit/main.c的start_kernel开始,下面对start_kernel进行分析,start_kernel代码如下</span>

 asmlinkage __visible void __init start_kernel(void)
501 {
502         char *command_line;
503         char *after_dashes;
504 
505         /*
506          * Need to run as early as possible, to initialize the
507          * lockdep hash:
508          */
509         lockdep_init();
510         set_task_stack_end_magic(&init_task);
511         smp_setup_processor_id();
512         debug_objects_early_init();
513 
514         /*
515          * Set up the the initial canary ASAP:
516          */
517         boot_init_stack_canary();
518 
519         cgroup_init_early();
520 
521         local_irq_disable();
522         early_boot_irqs_disabled = true;
523 
524 /*
525  * Interrupts are still disabled. Do necessary setups, then
526  * enable them
527  */
528         boot_cpu_init();
529         page_address_init();
530         pr_notice("%s", linux_banner);
531         setup_arch(&command_line);
532         mm_init_cpumask(&init_mm);
533         setup_command_line(command_line);
534         setup_nr_cpu_ids();
535         setup_per_cpu_areas();
536         smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
537 
538         build_all_zonelists(NULL, NULL);
539         page_alloc_init();
540 
541         pr_notice("Kernel command line: %s\n", boot_command_line);
542         parse_early_param();
543         after_dashes = parse_args("Booting kernel",
544                                   static_command_line, __start___param,
545                                   __stop___param - __start___param,
546                                   -1, -1, &unknown_bootoption);
547         if (!IS_ERR_OR_NULL(after_dashes))
548                 parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
549                            set_init_arg);
550 
551         jump_label_init();
552 
553         /*
554          * These use large bootmem allocations and must precede
555          * kmem_cache_init()
556          */
557         setup_log_buf(0);
558         pidhash_init();
559         vfs_caches_init_early();
560         sort_main_extable();
561         trap_init();//陷入门初始化,系统调用初始化
562         mm_init();//内存管理单元初始化
563 
564         /*
565          * Set up the scheduler prior starting any interrupts (such as the
566          * timer interrupt). Full topology setup happens at smp_init()
567          * time - but meanwhile we still have a functioning scheduler.
568          */
569         sched_init();//调度初始化
570         /*
571          * Disable preemption - early bootup scheduling is extremely
572          * fragile until we cpu_idle() for the first time.
573          */
574         preempt_disable();
575         if (WARN(!irqs_disabled(),
576                  "Interrupts were enabled *very* early, fixing it\n"))
577                 local_irq_disable();
578         idr_init_cache();
579         rcu_init();
580         context_tracking_init();
581         radix_tree_init();
582         /* init some links before init_ISA_irqs() */
583         early_irq_init();
584         init_IRQ();
585         tick_init();
586         rcu_init_nohz();
587         init_timers();
588         hrtimers_init();
589         softirq_init();
590         timekeeping_init();
591         time_init();
592         sched_clock_postinit();
593         perf_event_init();
594         profile_init();
595         call_function_init();
596         WARN(!irqs_disabled(), "Interrupts were enabled early\n");
597         early_boot_irqs_disabled = false;
598         local_irq_enable();
599 
600         kmem_cache_init_late();
601 
602         /*
603          * HACK ALERT! This is early. We're enabling the console before
604          * we've done PCI setups etc, and console_init() must be aware of
605          * this. But we do want output early, in case something goes wrong.
606          */
607         console_init();//控制台初始化
608         if (panic_later)
609                 panic("Too many boot %s vars at `%s'", panic_later,
610                       panic_param);
611 
612         lockdep_info();
613 
614         /*
615          * Need to run this when irqs are enabled, because it wants
616          * to self-test [hard/soft]-irqs on/off lock inversion bugs
617          * too:
618          */
619         locking_selftest();
620 
621 #ifdef CONFIG_BLK_DEV_INITRD
622         if (initrd_start && !initrd_below_start_ok &&
623             page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
624                 pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
625                     page_to_pfn(virt_to_page((void *)initrd_start)),
626                     min_low_pfn);
627                 initrd_start = 0;
628         }
629 #endif
630         page_cgroup_init();
631         debug_objects_mem_init();
632         kmemleak_init();
633         setup_per_cpu_pageset();
634         numa_policy_init();
635         if (late_time_init)
636                 late_time_init();
637         sched_clock_init();
638         calibrate_delay();
639         pidmap_init();
640         anon_vma_init();
641         acpi_early_init();
642 #ifdef CONFIG_X86
643         if (efi_enabled(EFI_RUNTIME_SERVICES))
644                 efi_enter_virtual_mode();
645 #endif
646 #ifdef CONFIG_X86_ESPFIX64
647         /* Should be run before the first non-init thread is created */
648         init_espfix_bsp();
649 #endif
650         thread_info_cache_init();
651         cred_init();
652         fork_init(totalram_pages);
653         proc_caches_init();
654         buffer_init();
655         key_init();
656         security_init();
657         dbg_late_init();
658         vfs_caches_init(totalram_pages);
659         signals_init();
660         /* rootfs populating might need page-writeback */
661         page_writeback_init();
662         proc_root_init();
663         cgroup_init();
664         cpuset_init();
665         taskstats_init_early();
666         delayacct_init();
667 
668         check_bugs();
669 
670         sfi_init_late();
671 
672         if (efi_enabled(EFI_RUNTIME_SERVICES)) {
673                 efi_late_init();
674                 efi_free_boot_services();
675         }
676 
677         ftrace_init();
678 
679         /* Do the rest non-__init'ed, we're now alive */
680         rest_init();//这个比较有意思,下文详细分析
681 }

start_kernel主要进行了各种初始化,对于我们比较敢兴趣的是
561         trap_init();//陷入门初始化,系统调用初始化
562         mm_init();//内存管理单元初始化
<pre name="code" class="cpp">569         sched_init();//调度初始化
<pre name="code" class="cpp">607         console_init();//控制台初始化
<pre name="code" class="cpp">680         rest_init();//这个比较有意思,下文详细分析
 
 
 

rest_init()源代码如下,分析详见注释

static noinline void __init_refok rest_init(void)
394 {
395         int pid;
396 
397         rcu_scheduler_starting();
398         /*
399          * We need to spawn init first so that it obtains pid 1, however
400          * the init task will end up wanting to create kthreads, which, if
401          * we schedule it before we create kthreadd, will OOPS.
402          */
403         kernel_thread(kernel_init, NULL, CLONE_FS);//创建了1号进程
404         numa_default_policy();
405         pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
406         rcu_read_lock();
407         kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
408         rcu_read_unlock();
409         complete(&kthreadd_done);
410 
411         /*
412          * The boot idle thread must execute schedule()
413          * at least once to get things moving:
414          */
415         init_idle_bootup_task(current);//初始化0号进程,即系统的idle进程
416         schedule_preempt_disabled();
417         /* Call into cpu_idle with preempt disabled */
418         cpu_startup_entry(CPUHP_ONLINE);
419 }

codeyangjun,原创作品转载请注明出处 ,《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值