linux的内核启动分析

来源:互联网 发布:软件自学网app 编辑:程序博客网 时间:2024/05/17 08:07

        Linux内核启动就是引导内核映像启动的过程。典型的内核映像是zImage,它包含自引导程序和压缩的vmlinux 2部分。因此,启动过程就是解压和启动vmlinux的过程。以ARM平台为例进行详细分析。

       启动过程从内核映像入口开始执行,解压vmlinux并且转换到虚拟地址空间,再调用统一的内核启动函数start_kernel(),从而启动整个linux系统。内核启动过程函数调用顺序如下图所示:


1.内核自引导程序

        zImage映像的入口代码是自引导程序。在自引导程序中会调用decompress_kernel()和call_kernel()两个重要的子程序。
        首先调用decompress_kernel()函数,解压压缩的vmlinux映像。然后调用call_kernel()函数,完成启动vmlinux的任务,它可以关闭CACHE,在寄存器中恢复系统平台号,然后跳转到vmlinux的入口。这样就把控制权完全的交给了vmlinux执行了。

2.vmlinux入口

        当程序执行到vmlinux的入口时,接着顺序执行内核的启动程序。这部分是汇编程序,在/arch/arm/kernel/head.s中,经过一系统的初始化之后,打开MMU,跳转到start_kernel()函数。

3.linux系统初始化

start_kernel()函数是linux内核通用的初始化函数。无论对于什么体系结构的linux,都要执行这个函数。start_kernel()函数负责初始化内核各个子系统,最后要调用rest_init(),启动一个init的内核线程,继续初始化。
kernel_thread(init,NULL,CLONE_FS| CLONE_SIGHAND); //启动init内核线程
在init内核线程中,将执行init()函数的程序。该函数负责完成挂接根文件系统、初始化设备驱动以及启动用户空间的init进程等重要工作。
populate_rootfs(); //安装文件系统
do_basic_setup(); //初始化设别驱动
prepare_namespace();//挂载根文件系统
完成以上初始化过程之后,系统彻底的启动运行了。接下来就要启动用户模式部分。

4.挂在根文件系统

          Linux能够在内存中虚拟磁盘文件系统,叫做ramdisk.由于在挂载根文件系统之前,有些启动需要访问初始化文件,那么需要有一个文件系统支持设备驱动的操作。如果内核配置了ramdisk设备和文件系统,执行populate_rootfs()函数就可以安装好ramdisk文件系统。
虚拟内存盘是通过软件将一部分内存(RAM)模拟为硬盘来使用的一种技术。相对于直接的硬盘文件访问来说,这种技术可以极大的提高在其上进行的文件访问的速度。但是RAM的易失性也意味着当关闭电源后这部分数据将会丢失。但是在一般情况下,传递到RAM盘上的数据都是在硬盘或别处永久贮存的文件的一个拷贝。经由适当的配置,可以实现当系统重启后重新建立虚拟盘。
初始化设备驱动程序之后再执行prepare_namespace()函数,它可以为linux系统挂接一个根文件系统。

5.初始化设备驱动

到这里的时候内核子系统已经基本初始化完成,CPU子系统已经正常工作,内存管理和进程管理已经正常运转,但是还没有使用任何设备。为了访问设备,接下来使用do_basic_setup()初始化内核设备驱动程序。在函数的最后调用do_initcalls()函数,执行所有设备的初始化。

6.启动用户空间init进程

linux系统挂载根文件系统成功后,要执行文件系统中的应用程序。init进程通过执行根文件系统中的init程序启动的。
内核成功挂载根文件系统后,通过run_init_process()函数执行应用程序。这是尝试的过程,若execute_command存在,则执行execute_command;如果不存在,则顺序知心/sbin/init、/etc/init、/bin/init、/bin/sh,知道有一个执行成功为止。
run_init_process()函数通过execve()函数执行应用程序,execve()又调用do_execuve()执行用户空间程序。
至此内核启动完成。
等待后续更新。。。



0 0