Linux 启动流程
init进程初始化系统
init 是 Unix和Linux系统中传统的初始化系统,根据运行级别来确定系统的状态。通过读取 /etc/inittab 文件来决定初始化过程。系统中的服务通常使用System V样式的初始化脚本(位于 /etc/init.d/)启动和管理。服务的启动时串行的,在启动下一个服务之前,先要等待当前服务完全启动。
1、加电自检
系统通电后,BIOS的自检 POST(Power-On-Self-Test)就是在系统启动时检查计算机的核心物理硬件组件是否正常工作。如果POST过程中发现了任何关键硬件的问题,系统通常不会继续启动,而是通过特定的蜂鸣声代码或屏幕上的错误信息来通知用户存在的问题。
2、加载内核
首先BIOS的自检通过后,加载引导加载程序(bootloader)如GRUB,负责加载内核和initrd/initramfs到内存中。
说明: initrd 或 initramfs 是在内核启动后,但在正式的文件系统被挂载之前,为了提供必要的设备驱动和工具而加载的。这确保了如果真实的根文件系统需要特定的硬件驱动才能访问,那么这些驱动在系统真正启动之前就已经可用。
3、初始化内核
在这一步完成加载必要的内核模块(这些模块通常是从 initramfs 中加载的,用于支持系统的主要根文件系统。)、设置内存,然后会会尝试启动PID为1的第一个用户空间进程(/sbin/init)
4、设运行级别
init 检查 /etc/inittab 中的默认运行级别,每个运行级别都有一组对应的脚本,一般是存放在/etc/rc.d/ 或 /etc/init.d/ 目录下的子目录中。然后init进程会根据指定的运行级别来启动执行相应的启动脚本。根据这些脚本来按顺序启动各种系统服务和守护进程
大多数linux发行版的运行级别:
-
0:关机
-
6:重启
-
1:安全模式
-
3:字符模式
-
5:图形界面模式
systemd进程初始化系统
systemd 是现代Linux发行版默认初始化系统,和init比起来有以下优点:
1、启动速度更快,因为采取了并行启动的方式,而init是顺序启动
2、更灵活:有些守护进程是当一个服务需要另一个服务时,它才会启动,不是在系统启动时无论如何都启动
3、使用称为“unit”的配置文件来描述服务和其他系统资源,unit文件提供了一种统一的方式来管理和控制各种类型的系统资源。
1、加电自检
BIOS/UEFI 会执行硬件自检并进行初始配置
2、加载内核
bios自检通过,会启动引导程序,引导程序加载 Linux 内核(从硬盘到内存)和初期 RAM 磁盘(initramfs)
3、内核初始化
内核首先初始化和配置硬件,如CPU、内存、设备等。之后它会设置内核数据结构并加载 initramfs 中的驱动程序。
4、启动pid为1的进程
内核初始化完成后会启动 PID 为 1 的进程,即初始化进程。
初始化进程启动后,会读取 /etc/systemd/system/default.target 来确定要启动的目标环境,并开始按依赖关系启动服务和其他单位。
说明:
systemd中的unit表示的是一种资源对象,例如:*.service 描述的就是一个服务对象。*.target代表一组unit对象,用来组织和管理一组 units,target 本身并不做实际的工作,但它确保了所依赖的或与其关联的其他 units 得到正确的处理。
例如: multi-user.target: 这个目标类似于传统的运行级别3,它表示系统应该运行在一个多用户、非图形环境中。当系统启动并尝试达到 multi-user.target 时,systemd 会确保所有与此 target 关联的服务、套接字等 units 都已经启动并运行。
常见的Linux bootloader
-
GRUB(GRand Unified Bootloader):是目前最常用的引导加载程序之一。它支持多种操作系统、文件系统和
-
LILO(LInux LOader):是较早的引导加载程序,现在使用得较少,但在某些场景下仍然有用
-
Syslinux:适用于轻量级的引导需求,如从USB驱动器或软盘引导。
linux的bootloader(grub)配置文件
grub是Linux发行版系统的常用bootloader,现在使用的是2.x版本,所以一般也叫作grub2.
系统加电启动时,固件(传统的BIOS或现代的UEFI)首先执行自检并初始化硬件。检查通过后,它读取磁盘的启动扇区(对于MBR结构)或EFI系统分区(对于GPT结构)。这些位置存放了GRUB的初阶启动代码,其作用是找到并加载第二阶段的代码。
在文件系统中,第二阶段的代码通常位于/boot/grub或/boot/grub2目录下。然而,因为在这个早期阶段文件系统还没有被挂载,GRUB不能直接从文件系统路径访问这些代码。但是GRUB自带了一些简单的文件系统驱动。
因此,当第二阶段的GRUB代码被加载时,它使用这些内置驱动直接从硬盘上读取所需的数据(不依赖于特定的操作系统内核或服务,获取配置信息,并进一步加载Linux内核和initramfs。
配置文件位置
这个配置文件定义了启动过程中所需的参数和菜单项这些内容。一般不能手动去修改grub.cfg 这个文件,而是通过编辑/etc/default/grub或者/etc/grub.d中的文件。然后再通过update-grub或grub2-mkconfig工具来重新生成/boot/grub.cfg 文件。 且如果配置错误,系统无法启动,所以修改前要备份。
例如:
GRUB_DEFAULT=0 # 指定默认选项是启动菜单中的第一个条目
GRUB_TIMEOUT_STYLE=hidden # 决定了GRUB菜单的显示样式。hidden表示默认情况下GRUB菜单是隐藏的,除非在启动时按下Shift或Esc键。
GRUB_TIMEOUT=0 # 这定义了GRUB菜单显示的秒数,设置为0意味着它会立即启动默认条目,不显示菜单。注意:当GRUB_TIMEOUT_STYLE设置为hidden时,你需要按Shift或Esc键来显示菜单,否则即使有非零的超时,也不会看到菜单。
GRUB_DISTRIBUTOR=lsb_release -i -s 2> /dev/null || echo Debian # 用于确定启动菜单中显示的发行版名称。这里使用了一个命令行命令来尝试获取系统的发行版信息;如果这个命令失败,它将默认显示“Debian”。
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" # 指定了默认情况下传递给Linux内核的参数。quiet表示减少启动过程中的输出;splash使系统显示一个启动画面(通常是一个图形动画或徽标)而不是文本模式的详细信息。
GRUB_CMDLINE_LINUX="" # 这是另一组传递给Linux内核的参数,但这些参数会在所有模式下(包括恢复模式)应用,而不仅仅是默认启动模式。此设置为空意味着没有额外的参数被添加。
加载initrd/initramfs目的
目的是为了解决先有鸡还是先有蛋的问题,为了挂载真实的根文件系统,可能需要某些驱动程序或工具,但这些驱动程序或工具可能位于该根文件系统上。initrd或initramfs为系统提供了一个临时解决方案,使其能够先拥有这些必要的资源,然后再挂载真正的根文件系统。
例如: 真实的根文件系统存在问题或损坏,那么在尝试挂载它的过程中可能会遇到困难或失败。在这种情况下,系统可能会“卡住”并停留在一个紧急恢复shell中。这个shell实际上是由initramfs提供的,允许管理员尝试进行故障排除。等到根文件系统被成功挂载后,进入正常的启动流程,临时的initramfs环境会被丢弃。
关机流程:
强制关机:
硬件会直接切断电源,导致计算机立即关机。不会给系统任何时间进行正常的清理操作,可能导致文件系统损坏或数据丢失。
正常关机:
-
系统进程接收到关机信号后进行相关的收尾工作,并优雅结束进程,此时系统会短暂等待,给进程一些时间进行清理操作
-
如果还没有结束的进程会收到SIGKILL信号,强制终止掉
-
相关的系统服务会被停止
-
卸载文件系统并停止内核
说明: 停止内核指中止内核的所有操作和活动,使其不再处理任务、调度进程或管理硬件
重启流程
硬重启
硬重启就是手动物理中断电源,然后再恢复。这个时候硬件会被初始化
1、手动物理断电计算机内的操作立即停止,没有任何正常的关闭或资源释放过程
2、手动恢复电源启动
3、进入启动流程,bios自检、bootloader加载、内核加载、服务启动等。
软重启
1、输入相关指令,发送信号停止服务,卸载文件系统、停止内核。
2、系统关机后(完全关机之前),操作系统会发出一个特殊的命令或信号,告诉计算机硬件执行重启。
3、进行硬件初始化(bios自检、bootloader加载、内核加载、服务启动等)