1、Linux启动过程
开机自检
linux开机加电后,系统开始开机自检,该过程主要对计算机各种硬件设备进行检测,如CPU、内存、主板、硬盘、CMOS芯片等。
如果出现致命故障则停机,并且由于初始化过程还没完成,所以不会出现任何提示信号;
如果出现一般故障则会发出声音等提示信号,等待故障清除;若未出现故障,加电自检完成。
当打开计算机电源,计算机会首先加载基本输入输出系统(Basic Input Output System )。BIOS程序一般被存放在主板ROM(只读存储芯片)之中、即使在关机或掉电以后该程序也不会丢失。
BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息、PNP特性等等。在此之后,计算机就知道应该去读取哪个硬件设备了。
加载主引导记录
主引导记录(MBR,Master Boot Record)是计算机开机以后访问硬盘时所必须要读取的第一个扇区,位于硬盘的第0柱面第0磁道第一扇区,大小为512字节。
**MBR 中最主要的功能就是存储、启动、加载启动引导程序。**诸如LILO、GRUB这些引导程序(BootLoader)都是直接安装在MBR中。
BootLoader启动
BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。
在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。
加载内核
GRUB把内核加载到内存后展开并运行, 此时GRUB的任务已经完成,接下来内核将会接管并完成,同时把initrd加载到内存中并运行。
initrd文件其实是一个虚拟的根文件系统,里面有bin、lib、lib64、sys、var、etc、sysroot、 dev、proc、tmp等根目录,它的功能就是将内核与真正的根建立联系,内核通过它加载根文件系统的驱动程序,然后以读写方式挂载根文件系统,至此, 内核加载完成。
执行init
内核加载进内存运行并以读写方式挂载完根文件系统后,执行第一个用户进程init,init首先运行/etc/init/rcS.conf脚本,对系统做初始化设置。init进程的一大任务,就是去运行这些开机启动的程序。
Linux预置七种运行级别(0-6),Linux允许为不同的场合,分配不同的开机启动程序。
在该过程中主要执行以下操作:
获得网络环境
挂载设备
开机启动画面Plymouth(取替了过往的 RHGB)
判断是否启用SELinux
显示于开机过程中的欢迎画面
初始化硬件
用户自定义模块的加载
配置内核的参数
设置主机名
同步存储器
设备映射器及相关的初始化
初始化软件磁盘阵列(RAID)
初始化 LVM 的文件系统功能
检验磁盘文件系统(fsck)
设置磁盘配额(quota)
重新以可读写模式挂载系统磁盘
更新quota(非必要)
启动系统虚拟随机数生成器
配置机器(非必要)
清除开机过程当中的临时文件
创建ICE目录
启动交换分区(swap)
将开机信息写入/var/log/dmesg文件中
打印登录提示符
系统初始化完成后,init给出用户登录提示符(login)或者图形化登录界面,用户输入用户和密码登陆后,系统会为用户分配一个用户uid和组gid,这两个ID是用户的身份标识,用于检测用户运行程序时的身份验证。
登录成功后,整个系统启动流程运行完毕!
树莓派3B/4B的启动流程如下图。
(1)bootcode.bin:由GPU运行的引导程序。在树莓派3B版本中,它放置在SD卡上;而树莓派4B版本中,它已被固化在BootROM里。不开源,可到官网下载。
(2)start.elf/start4B.elf:GPU固件。不开源,可到官网下载。
过程记录
1) 树莓派上电启动
树莓派上电后,SoC 中的 第一启动程序 首先被执行,其作用是挂载 SD 卡上的 FAT32 分区,从而加载下一阶段的 bootloader。这部分程序被固化在 SoC 的 ROM 中,用户无法进行修改。
4B 在芯片内部增加了一块 EEPROM 来规避风险(由于 4B 硬件升级,导致启动过程较为复杂,如果将代码都写到 ROM 中,会增加复杂度以及引入可能的 BUG ),4B 上电运行 SPI 连接的 EEPROM 中的 bootloader 代码。
2) 树莓派执行 bootloader
在这个阶段,树莓派会加载 SD 卡上的 bootcode.bin
(bootloader
) 文件作为第二阶段的启动程序。bootloader
会启动GPU并加载第三阶段的启动器start.elf
。
需要注意,4B 上不使用 bootcode.bin
,因为它已由板载 EEPROM
中的启动代码替换。
3) 树莓派启动内核
start.elf
读取存放系统配置的文件 config.txt
,根据其内容设置 CPU 运行参数及内存分配情况,随后将用户代码加载至内存,启动 CPU;
CPU 启动后,加载内核进行启动。
系统会先搜寻 config.txt
中参数 kernel=xxx
指定的文件作为接下来接受系统控制权的对象,树莓派默认该文件是 linux 内核,我们可以替换为用 uboot
作为新一个 bootloader
然后之后再去启动 linux 内核。
如果 config.txt
里没指定 kernel
参数,则默认是先后搜寻 kernel8.img
、kernel8-32.img
、kernel7.img
、kernel.img
,分别对应 ARMv8-aarch64
、ARMv8-aarch32
、ARMv7
和之前版本的。
树莓派启动注意事项
SD 卡里的 boot 需要包含如下文件:
- overlays:存放设备树,必须有
- bcm2711-rpi-4-b:设备树文件
- bootcode.bin:第二阶段的bootloader,必须存在(4B除外)
- fixup*.dat :链接器文件,与 start*.elf 文件匹配
- start*.elf :GPU基本固件,第三阶段启动器
- kernel.img :linux内核镜像,也可以为uboot,然后再进一步启动内核
- config.txt :该文件是启动过程第三阶段用来读取参数的。
- cmdline.txt :是树莓派原生系统启动时传给内核的参数