Linux source code

init:

当PC启动时,Intel系列的CPU首先进入的是实模式,并开始执行位于地址0xFFFF0处的代码,也就是ROM-BIOS起始位置的代码。BIOS先进行一系列的系统自检,然后初始化位于地址0的中断向量表。最后BIOS将启动盘的第一个扇区装入到0x7C00,并开始执行此处的代码.这就是对内核初始化过程的一个最简单的描述。

    最初,Linux核心的最开始部分是用8086汇编语言编写的。当开始运行时,核心将自己装入到绝对地址0x90000,再将其后的2k字节装入到地址0x90200处,最后将核心的其余部分装入到0x10000。

    当系统装入时,会显示Loading...信息。装入完成后,控制转向另一个实模式下的汇编语言代码boot/Setup.S。Setup部分首先设置一些系统的硬件设备,然后将核心从0x10000处移至0x1000处。这时系统转入保护模式,开始执行位于0x1000处的代码。

    接下来是内核的解压缩。0x1000处的代码来自于文件Boot/head.S,它用来初始化寄存器和调用decompress_kernel( )程序。decompress_kernel( )程序由Boot/inflate.c, Boot/unzip.c 和Boot/misc.c组成。解压缩后的数据被装入到了0x100000处,这也是Linux不能在内存小于2M的环境下运行的主要原因。

    解压后的代码在0x1010000处开始执行,紧接着所有的32位的设置都将完成: IDT、GDT和LDT将被装入,处理器初始化完毕,设置好内存页面,最终调用start_kernel过程。这大概是整个内核中最为复杂的部分。

以上一段引自http://www.joyfire.net/jln/kernel/1.html

初始化顺序:

416 asmlinkage void __init start_kernel(void)
417 {
418         char * command_line;
419         extern struct kernel_param __start___param[], __stop___param[];
420 /*
421 * Interrupts are still disabled. Do necessary setups, then
422 * enable them
423 */
424         lock_kernel();
425         page_address_init();
426         printk(linux_banner);
427         setup_arch(&command_line);
428         setup_per_cpu_areas();
429
430         /*
431          * Mark the boot cpu "online" so that it can call console drivers in
432          * printk() and can access its per-cpu storage.
433          */
434         smp_prepare_boot_cpu();
435
436         /*
437          * Set up the scheduler prior starting any interrupts (such as the
438          * timer interrupt). Full topology setup happens at smp_init()
439          * time - but meanwhile we still have a functioning scheduler.
440          */
441         sched_init();
442         /*
443          * Disable preemption - early bootup scheduling is extremely
444          * fragile until we cpu_idle() for the first time.
445          */
446         preempt_disable();
447         build_all_zonelists();
448         page_alloc_init();
449         printk("Kernel command line: %s/n", saved_command_line);
450         parse_early_param();
451         parse_args("Booting kernel", command_line, __start___param,
452                    __stop___param - __start___param,
453                    &unknown_bootoption);
454         sort_main_extable();
455         trap_init();
456         rcu_init();
457         init_IRQ();
458         pidhash_init();
459         init_timers();
460         softirq_init();
461         time_init();
462
463         /*
464          * HACK ALERT! This is early. We're enabling the console before
465          * we've done PCI setups etc, and console_init() must be aware of
466          * this. But we do want output early, in case something goes wrong.
467          */
468         console_init();
469         if (panic_later)
470                 panic(panic_later, panic_param);
471         profile_init();
472         local_irq_enable();
473 #ifdef CONFIG_BLK_DEV_INITRD
474         if (initrd_start && !initrd_below_start_ok &&
475                         initrd_start < min_low_pfn << PAGE_SHIFT) {
476                 printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
477                     "disabling it./n",initrd_start,min_low_pfn << PAGE_SHIFT);
478                 initrd_start = 0;
479         }
480 #endif
481         vfs_caches_init_early();
482         mem_init();
483         kmem_cache_init();
484         numa_policy_init();
485         if (late_time_init)
486                 late_time_init();
487         calibrate_delay();
488         pidmap_init();
489         pgtable_cache_init();
490         prio_tree_init();
491         anon_vma_init();
492 #ifdef CONFIG_X86
493         if (efi_enabled)
494                 efi_enter_virtual_mode();
495 #endif
496         fork_init(num_physpages);
497         proc_caches_init();
498         buffer_init();
499         unnamed_dev_init();
500         security_init();
501         vfs_caches_init(num_physpages);
502         radix_tree_init();
503         signals_init();
504         /* rootfs populating might need page-writeback */
505         page_writeback_init();
506 #ifdef CONFIG_PROC_FS
507         proc_root_init();
508 #endif
509         check_bugs();
510
511         acpi_early_init(); /* before LAPIC and SMP init */
512
513         /* Do the rest non-__init'ed, we're now alive */
514         rest_init();
515 }

产生init进程:

371 static void noinline rest_init(void)
372         __releases(kernel_lock)
373 {
374         kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
375         numa_default_policy();
376         unlock_kernel();
377         preempt_enable_no_resched();
378         cpu_idle();
379 }

init进程函数:

625 static int init(void * unused)
626 {
627         lock_kernel();
628         /*
629          * Tell the world that we're going to be the grim
630          * reaper of innocent orphaned children.
631          *
632          * We don't want people to have to make incorrect
633          * assumptions about where in the task array this
634          * can be found.
635          */
636         child_reaper = current;
637
638         /* Sets up cpus_possible() */
639         smp_prepare_cpus(max_cpus);
640
641         do_pre_smp_initcalls();
642
643         fixup_cpu_present_map();
644         smp_init();
645         sched_init_smp();
646
647         /*
648          * Do this before initcalls, because some drivers want to access
649          * firmware files.
650          */
651         populate_rootfs();
652
653         do_basic_setup();
654
655         /*
656          * check if there is an early userspace init.  If yes, let it do all
657          * the work
658          */
659         if (sys_access((const char __user *) "/init", 0) == 0)
660                 execute_command = "/init";
661         else
662                 prepare_namespace();
663
664         /*
665          * Ok, we have completed the initial bootup, and
666          * we're essentially up and running. Get rid of the
667          * initmem segments and start the user-mode stuff..
668          */
669         free_initmem();
670         unlock_kernel();
671         system_state = SYSTEM_RUNNING;
672         numa_default_policy();
673
674         if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
675                 printk("Warning: unable to open an initial console./n");
676
677         (void) sys_dup(0);
678         (void) sys_dup(0);
679        
680         /*
681          * We try each of these until one succeeds.
682          *
683          * The Bourne shell can be used instead of init if we are
684          * trying to recover a really broken machine.
685          */
686
687         if (execute_command)
688                 run_init_process(execute_command);
689
690         run_init_process("/sbin/init");
691         run_init_process("/etc/init");
692         run_init_process("/bin/init");
693         run_init_process("/bin/sh");
694
695         panic("No init found.  Try passing init= option to kernel.");
696 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值