简单理解嵌入式linux启动过程

2019-07-12 14:10发布

  1. BootLoader。BootLoader有多种工具,常见的如u-boot,Blob等等,其基本的作用就是加载(load)内核镜像,设备树,ramdisk(注意ram,即会加载到内存中),将这些东西加载到内存的指定地址处(如通过mkimage生成的镜像,在u-boot里使用bootm指令来加载)。Bootloader是一个裸机程序。U-Boot是arm平台上标准的BootLoader。
    U-Boot的配置是以宏的形式定义在C的.h 文件中的,以宏的形式定义了要执行的Shell脚本。定义了很多种启动方式,如sdbootusbbootnandboot等等。不同的启动方式用了不同的指令从不同的地方加载,比如sdboot中就是 load mmc ...,usbboot就是 load usb ...,nandboot是nand read ...
  2. 启动内核。BootLoader之后开始启动内核,这个过程有Kernel command line,即内核启动时的一些参数,如初始化串口等。BootLoader可以设置bootargs,bootargs在BootLoader阶段是不起作用的,是传给内核的,默认会覆盖掉内核中本来的Kernel command line,但是也可以在内核中设置让内核不使用BootLoader传过来的Bootargs,或者将其附加到原本的command line后面(可以通过make menuconfig 中的Boot options->Kernel command line type设置)。
  3. 在内核启动过程,会去加载根文件系统,通过Kernel command line中的 root=..,如root来加载指定位置的根文件系统。首先知道什么是文件系统,“文件系统是对一个存储设备上的数据和元数据进行组织的机制”,比如在ubuntu上插一个U盘,挂载到linux的一个文件夹中,这个U盘中的数据和ubuntu本来的数据就是两个文件系统,可以用df查看一下。
    之前我一直以为ramdisk就是根文件系统,其实不是。根文件系统其实就是一些系统文件夹,比如我们在ubuntu下用cd / 就看到系统根目录,有etc,bin等文件夹,其中保存了ubuntu的环境变量等系统配置。嵌入式的根文件系统里边就是etc,bin这些东西。
    根问件系统一般有三种类型,基于存储器,基于内存(ram),基于网络。
    • ramdisk是一种基于内存的文件系统(注意名字中有个ram),是使用BootLoader对应的工具制作的,会在BootLoader阶段load,加载到内存中(在U-Boot就是使用bootm这个指令来加载到内存中),ramdisk占用内存空间,不占用sd卡或硬盘空间。BootLoader将ramdisk镜像加载到内存中后,内核如果要用它作为根文件系统就在kernel command line 里设置root=/dev/ram。但是ramdisk的缺点很明显,因为是基于内存的根文件系统,所以直接对其进行的修改在掉电后是不会保存的,只能通过重新制作在进行修改,而且其占用内存空间,但内存空间往往很小。
    • 使用基于存储器的根文件系统时,即root=/dev/mmc..,一般都要给 kernel command line 加上 rootwait这个选项,来避免加载根文件系统时,读写sd卡的驱动还没初始化完成。同时注意检查启动log的kernel command line 是否被BootLoader中的bootargs覆盖。

总结:

在移植linux时,多注意看启动时的log,如果是内核启动之前(如log没有打印到starting kernel)的问题,那么就去看Bootloader的配置是否正确,如果是之后,那就去看内核的配置是否有问题,如kernel command line 是否被BootLoader中的bootargs覆盖。 以上为最近在zedboard上弄xilinx linux的一些个人总结,之后再修改和补充。