Linux内核最初只是由芬兰人李纳斯·托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的。Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。Linux能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。
Linux内核实现了操作系统的基本功能,我们一般用的是Linux发行版。Linux发行版说简单点就是将Linux内核与应用软件做一个打包。目前市面上较知名的发行版有:Ubuntu、RedHat、CentOS、Debian、Fedora、SuSE、OpenSUSE、TurboLinux、BluePoint、RedFlag、Xterm、SlackWare等。
Linux 系统的启动过程基本分为引导和启动两个阶段。简单讲就是计算机开机后引导进入硬盘,然后启动硬盘的操作系统两个过程。引导阶段始于打开电源开关,终于内核初始化完成和systemd进程成功运行。启动阶段接管剩余的工作,直到操作系统进入可操作状态。Linux系统启动其实并不算复杂,引导和启动两个过程比较容易理解,但是要搞清楚linux系统启动还要再深入了解详细的启动过程,具体分为四个过程:
-
BIOS上电自检(POST)
-
引导装载程序(GRUB2)
-
加载LINUX内核
-
启动systemd进程
Linux有很多的发行版本,各发行版之间和新旧版本之间使用的程序也存在差异,但是linux系统启动过程步骤大致相同。grub2和systemd组合是目前linux操作系统使用最多的启动方式。systemd更是父进程最优解决方案,取代了旧版本的init进程和upstart进程(init和upstart都是系统初始化进程,或者称为进程之父,init是串行启动,upstart是基于事件驱动的并行启动,由ubuntu发行版开发)。
(一)BIOS上电自检
BIOS上电自检其实跟操作系统没有任何关系,是所有计算机启动时都必须执行的过程,其目的是检测计算机各种硬件是否正常工作,只有BIOS自检通过才会进一步引导磁盘启动系统,如果自检存在问题则会终端启动过程。
BIOS 上电自检确认硬件的基本功能正常,然后产生一个 BIOS 中断 INT 13H,该中断指向某个接入的可引导设备的引导扇区。它所找到的包含有效的引导记录的第一个引导扇区将被装载到内存中,并且控制权也将从引导扇区转移到此段代码。
引导扇区是引导加载器真正的第一阶段。大多数 Linux 发行版本使用的引导加载器有三种:GRUB、GRUB2 和 LILO。GRUB2 是最新的,也是相对于其他老的同类程序使用最广泛的。
(二)引导加载器GRUB2
GRUB2 全称是 GRand Unified BootLoader,Version 2(第二版大一统引导装载程序)。它是目前流行的大部分 Linux 发行版本的主要引导加载程序。GRUB2 是一个用于计算机寻找操作系统内核并加载其到内存的智能程序。
GRUB2引导加载程序最主要作用都是将内核加载到内存并运行。基本上GRUB2的工作分为3个阶段,分别是MBR主引导记录
的引导镜像boot.img
执行、core.img
镜像执行、加载LINUX内核。
1.MBR引导记录(boot.img)
MBR是硬盘的第1个 512 字节的扇区,包含引导程序boot.img
、分区表及分隔标识,MBR总计512字节,引导程序占446个字节。BIOS上电自检完毕后,BIOS将从接入的硬盘中扫描MBR扇区,从MBR中加载boot.img
引导镜像到内存中。由于引导记录必须非常的小,它不可能非常智能,且不能理解文件系统结构。因此boot.img
引导程序的唯一功能就是定位并加载下一个步骤的镜像。
2.加载文件系统(core.img)
MBR的引导程序boot.img
加载完毕后由引导程序加载core.img
镜像程序,为了能让引导程序找到core.img
,它必须存放于MBR和硬盘第一个分区之间,该空间有62个512字节的扇区共计 31744 字节,相对MBR有更大的存储空间,足以容纳通用的文件系统驱动程序,如标准的EXT
和其它的 Linux 文件系统,如 FAT
和NTFS
等。因此执行core.img
的主要目的是加载文件系统。
3.加载LINUX内核
这个部分因为加载了文件系统,因此可以对文件系统的文件进行操作。这个步骤没有前面两个步骤的img镜像,而是加载/boot/grub2/i386-pc
目录下的一些内核运行时模块。该步骤主要是定位和加载 Linux 内核到内存中,并转移控制权到内核。内核的相关文件位于 /boot
目录下,这些内核文件可以通过其文件名进行识别,其文件名均带有前缀 vmlinuz
。你可以列出 /boot
目录中的内容来查看操作系统中当前已经安装的内核。
(三)启动systemd进程
grub2引导加载程序加载linux内核后接下来就是启动/lib/systemd/systemd
进程。systemd是操作系统启动的第一个进程,因为有了systemd进程linux系统才具有可操作性,才能基于systemd创建更多的进程,因此systemd也被称为进程之父。
在传统的Linux操作系统中,系统的启动主要由init(sysvinit)进程来处理,但是init进程是串行启动相关的服务和守护进程,导致启动过程耗时太长,早期Linux主要应用在服务器中,不用频繁重启init进程基本满足使用需求。随着Linux系统不断优化,基于Linux桌面操作系统发行版逐渐被应用在个人计算机中,面向普通用户的linux系统如果开机需要经过漫长的过程,显然用户是不能接受的,因此systemd就应运而生了,它的目的就是取代init进程,通过并行启动服务和守护进程,加快开机速度。
1.目标态
systemd会将操作系统启动到某个状态,比如单用户模式状态、多用户状态、图形界面状态等等,这些状态我们称为“目标态”。systemd执行的第一个目标是/usr/lib/systemd/system/default.target
。在图形桌面的linux系统中default.target
实际上是指向/usr/lib/systemd/system/graphical.target
的软链接(Linux里的软链接的作用与Windows的快捷方式一样)。graphical.target
即为图形化界面状态。
systemd中的目标态在传统的init进程中称为运行级别runlevel
,相比init进程以数字区分状态,systemd中的目标态更易于理解。而且systemd的兼容init的运行级别,通过运行级别也可以让systemd到达相应的目标态。
SystemV运行级别 | systemd目标态 | systemd目标态别名 | 描述 |
---|---|---|---|
halt.target | 停止系统运行但不切断电源。 | ||
0 | poweroff.target | runlevel0.target | 停止系统运行并切断电源. |
S | emergency.target | 单用户模式,没有服务进程运行,文件系统也没挂载。这是一个最基本的运行级别,仅在主控制台上提供一个 shell 用于用户与系统进行交互。 | |
1 | rescue.target | runlevel1.target | 挂载了文件系统,仅运行了最基本的服务进程的基本系统,并在主控制台启动了一个 shell 访问入口用于诊断。 |
2 | runlevel2.target | 多用户,没有挂载 NFS 文件系统,但是所有的非图形界面的服务进程已经运行。 | |
3 | multi-user.target | runlevel3.target | 所有服务都已运行,但只支持命令行接口访问。 |
4 | runlevel4.target | 未使用。 | |
5 | graphical.target | runlevel5.target | 多用户,且支持图形界面接口。 |
6 | reboot.target | runlevel6.target | 重启。 |
default.target | 这个目标态是总是 multi-user.target 或 graphical.target 的一个符号链接的别名。systemd 总是通过 default.target 启动系统。default.target 绝不应该指向 halt.target、 poweroff.target 或 reboot.target。 |
终端中执行命令cat /usr/lib/systemd/system/graphical.target
,可以看到graphical.target
的内容:
lee@lee-virtual-machine:~/桌面$ cat /usr/lib/systemd/system/graphical.target
[Unit]
Description=Graphical Interface
Documentation=man:systemd.special(7)
Requires=multi-user.target
Wants=display-manager.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target display-manager.service
AllowIsolate=yes
值得注意的是Requires=multi-user.target
和After=multi-user.target rescue.service rescue.target display-manager.service
,表示启动时先到达multi-user.target
目标态,也就是说图形化界面状态是基于多用户状态的。
每个目标态有一个在其配置文件中描述的依赖集,systemd 需要首先启动其所需依赖,这些依赖服务是 Linux 主机运行在特定的功能级别所要求的服务。当配置文件中所有的依赖服务都加载并运行后,即说明系统运行于该目标级别。
2.串行和并行启动
前面说到systemd是为解决init的串行启动导致系统启动慢而开发的,systemd实现了服务和守护程序并行启动加快计算机开机过程。但是操作系统的启动某些服务或者进程是存在依赖关系的,init进程的串行启动有明确的启动顺序,启动过程几乎不会出现缺少依赖的问题,而systemd中如果全部都实行并行启动,那么某些服务或进程将会启动失败,这时候就需要一个明确的启动顺序。systemd的并行启动是分阶段的,某个阶段中并行启动完成后,在进入下一阶段在并行启动一批进程,简单说就是systemd是串行并行相结合解决的依赖项启动问题。
systemd从上往下启动,sysinit.target
、basic.target
、multi-user.target
、graphical.target
等目标态按顺序到达(串行),而各个目标态中的单元可以并行启动。
- sysinit.target:并行完成如文件系统挂载、交换文件设置、设备管理器的启动、随机数生成器种子设置、低级别系统服务初始化、加解密服务启动(如果一个或者多个文件系统加密的话)到达
sysinit.target
状态。 - basic.target:启动下一目标态所需的可执行文件的目录路径、通信sockets,以及定时器等单元。
- multi-user.target、graphical.target初始化完成,至此Linux系统已完成启动过程。
在
/usr/lib/systemd/system
目录下执行命令ls -l
查看文件列表,可以清楚的看出各个目标态的关系,以及sysv的运行级别对应的systemd目标态。