linux内核启动过程(一)

    技术2022-05-12  9

     

    一:启动

    当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过程。这大概是整个内核中最为复杂的部分。

    [系统开始运行]Linux kernel 最早的C代码从汇编标记startup_32开始执行

    |startup_32:|start_kernel|lock_kernel|trap_init|init_IRQ|sched_init|softirq_init|time_init|console_init|#ifdef CONFIG_MODULES|init_modules|#endif|kmem_cache_init|sti|calibrate_delay|mem_init|kmem_cache_sizes_init|pgtable_cache_init|fork_init|proc_caches_init|vfs_caches_init|buffer_init|page_cache_init|signals_init|#ifdef CONFIG_PROC_FS|proc_root_init|#endif|#if defined(CONFIG_SYSVIPC)|ipc_init|#endif|check_bugs|smp_init|rest_init|kernel_thread|unlock_kernel|cpu_idle

    ·startup_32 [arch/i386/kernel/head.S]·start_kernel [init/main.c]·lock_kernel [include/asm/smplock.h]·trap_init [arch/i386/kernel/traps.c]·init_IRQ [arch/i386/kernel/i8259.c]·sched_init [kernel/sched.c]·softirq_init [kernel/softirq.c]·time_init [arch/i386/kernel/time.c]·console_init [drivers/char/tty_io.c]·init_modules [kernel/module.c]·kmem_cache_init [mm/slab.c]·sti [include/asm/system.h]·calibrate_delay [init/main.c]·mem_init [arch/i386/mm/init.c]·kmem_cache_sizes_init [mm/slab.c]·pgtable_cache_init [arch/i386/mm/init.c]·fork_init [kernel/fork.c]·proc_caches_init·vfs_caches_init [fs/dcache.c]·buffer_init [fs/buffer.c]·page_cache_init [mm/filemap.c]·signals_init [kernel/signal.c]·proc_root_init [fs/proc/root.c]·ipc_init [ipc/util.c]·check_bugs [include/asm/bugs.h]·smp_init [init/main.c]·rest_init·kernel_thread [arch/i386/kernel/process.c]·unlock_kernel [include/asm/smplock.h]·cpu_idle [arch/i386/kernel/process.c]

    start_kernel( )程序用于初始化系统内核的各个部分,包括:

    *设置内存边界,调用paging_init( )初始化内存页面。*初始化陷阱,中断通道和调度。*对命令行进行语法分析。*初始化设备驱动程序和磁盘缓冲区。*校对延迟循环。

    最后的function'rest_init' 作了以下工作:

    ·开辟内核线程'init'·调用unlock_kernel·建立内核运行的cpu_idle环, 如果没有调度,就一直死循环

    实际上start_kernel永远不能终止.它会无穷地循环执行cpu_idle.

    最后,系统核心转向move_to_user_mode( ),以便创建初始化进程(init)。此后,进程0开始进入无限循环。

    初始化进程开始执行/etc/init、/bin/init 或/sbin /init中的一个之后,系统内核就不再对程序进行直接控制了。之后系统内核的作用主要是给进程提供系统调用,以及提供异步中断事件的处理。多任务机制已经建立起来,并开始处理多个用户的登录和fork( )创建的进程。

    [init]init是第一个进程,或者说内核线程

    |init|lock_kernel|do_basic_setup|mtrr_init|sysctl_init|pci_init|sock_init|start_context_thread|do_init_calls|(*call())-> kswapd_init|prepare_namespace|free_initmem|unlock_kernel|execve


    最新回复(0)