Physical Address:
ChongQing,China.
WebSite:
最近这段时间一直在折腾Linux系统,原因是我想在我的系统开机/关机时自动发送提醒到我的电报机器人,由此而衍生到我需要去关注系统开机与关机时的过程以确定何时发送这类提醒。起初我Google了很多内容,只可惜大多数内容都过于老旧,已经不再适合当下的Linux系统,所以就自己总结了一下,把这些总结放在这里,希望能够帮助到大家。
今天要探讨的是Linux系统的启动过程,我简单将其分为两个阶段:内核启动阶段与操作系统启动阶段,,大体上包括五个步骤,具体可以参考下图:
接下来我将会就这五个阶段简单做一下介绍。
严格来讲,内核启动阶段其实并不只是内核的启动。而内核的主要工作包括:
实际上在内核运行之前还有一些更基础的工作,它们分别是加载BIOS、读取MBR、加载Bootloader、内核启动。
BIOS是Basic Input/Output System的简称,也称之为基本输入输出系统。在我们的系统通电后BIOS会对计算机硬件进行检查,确保基本的硬件状态,这个阶段也称之为Power-on Self-test,简称为POST。在加载BIO阶段,其主要的任务包括:
BIOS通常使用汇编语言编写,存储在EEPROM(带电可擦除可编程只读存储器)内,即使掉电也能保存数据。
MBR是Master Boot Record的简称。硬件自检完成后,BIOS会将程序控制权移交给排在第一位的存储设备。程序会读取该设备的第一个扇区,也就是前512个字节。如果这512个字节的最后两个字节为55 AA则表明该设备可以用于启动,反之则不能启动。程序控制权移交给下一个设备。其中这512个字节就被称为“主引导记录”(Master boot record),简称为MBR。
主引导记录包括三部分内容:
(1):1-446字节是调用操作系统的机器码
(2):447-510字节是分区表(partition table),将硬盘分为若干个分区
(3):511-512字节是主引导记录签名,为55 AA表明系统可以正常启动。
如果MBR读取正常,接下来将会到加载bootloader阶段,bootloader是操作系统运行内核前的一小段引导程序,通过这一小段引导程序我们将会进行初始化硬件设备,建立内存空间的映射等工作。Bootloader有很多种,Linux中常用的包括GRUB、LILO等。我们一般使用GRUB,这是因为GRUB对文件系统有更好的支持。这一阶段主要是为了Linux Kernel的运行做准备。
GRUB的加载按照grub.cfg文件进行,grub.cfg的文件位于/boot/grub目录。以下为grub.cfg文件内容的截图:
注:截图来自于Ubantu 20.0 LTS版本,其他发行版可能会存在差异。
在GRUB引导菜单中,会提示我们选择内核版本。在我们选择了对应的内核版本后,就开始进入了操作系统的启动阶段。
当我们选择了某一特定的内核版本之后,其对应的镜像将会加载至内存中。同时会加载相应文件系统,并将存储设备进行mount,之后将启动init进程。
当内核启动完成后,系统会找到位于/sbin目录的init文件并执行该可执行文件。在当下流行的Linux发行版中,由于引入了Systemd,/sbin/init实际上是链接到了/lib/systemd/systemd文件,如下图所示:
在SystemV的Linux系统中,init进程会根据/etc/inittab文件完成各个系统服务的启动。具体的启动过程根据inittab中的run level,找到/etc/rcX.d文件夹(X与run level保持一致)。
Ubantu中Run level的含义如下:
与Run level对应,在/etc目录下都有一个单独的文件夹,不同的运行级别则会根据对应的文件夹内的配置运行相应的服务。
相信大家会看到这里有一个rcS.d文件夹,那这个文件夹是干嘛的呢。在Google了一堆后,我找到了比较可信的说法,那就是:rcS.d文件夹内是系统必须运行的服务,这里的S代表Startup。无论系统设定的Run level是几,rcS.d文件夹的服务都会被执行。有的文章中解释说S代表Single,也就是单用户模式,所以rcS.d文件夹下的内容与rc1.d文件夹下内容相同。但是根据我的观察,两者其实是不同的,具体可以参看下面的截图:
此外,根据上面的图片我们可以发现,rcX.d文件夹内的内容实际上是链接到了init.d文件夹内。所以真正启动的服务其实都在init.d文件夹下。
以上所述,其实是SystemV结构的Linux系统。但是在SystemV这种结构的Linux系统中我们可以看出,Init过程实际上是一个串行过程,只有一个进程启动完才会启动下一个进程,而且init进程本身只是执行启动脚本,不参与各个服务具体的内部任务,需要在脚本中处理很多情况,导致脚本内容通常很臃肿。在引入了Systemd后,/etc/inittab文件则不复存在,init进程变为了systemd进程,与之对应的配置之文件则位于/etc/systemd/system内,其具体内容可以参考如下图片:
关于systemd的配置文件的相关解读,由于篇幅有限,本次不做过多介绍,后面有机会再做介绍。
以上就是Linux系统启动的一个大体过程,其中有很多细节还可以深挖,感兴趣的小伙伴可以自行探索一下。