Skip to content

系统启动过程

早期开机方式

为什么这里要特别强调早期呢?因为现在启动方式已经变了。这时肯定就有很多人有疑惑了, 既然都变了, 为什么还要讲旧的呢?

其实这种早期的启动方式还是很有必要学的。原因有以下几点。

  • 现在的启动方式也是通过早期的方式优化过来的, 有一定的关联性。
  • 有很多老项目, 现在还在用这种init进程的启动方式。
  • 新的启动方式大规模使用的时间并不久, 也就在2018年左右才开始普及, 现在百度搜索linux系统的开机过程, 显示的几乎全部是init进程的启动方式。

linux系统的开机过程很重要, 但是真正重要的其实就那么几步。

alt text

早期开机过程

我把开机过程分为了以下六个阶段:

一、从开机自检(BIOS)到加载内核阶段

  • 这一阶段对应的知识我们完全不必掌握, 知道这是从开机到载入内核的过程就可以了
  • 注意: 这个不重要只是对我们想做C++后端的人来说, 对于做嵌入式的朋友, 这是绝对的核心, 如果是运维的话, 这些还是应该掌握的

二、启动init进程:

使用命令 ps -ef | more 查看进程

  • 这个进程是linux系统的第一个进程, PID为1, 又叫超级进程, 也叫根进程。
  • 负责产生其它所有的用户进程, 所有的进程都被挂在这个进程下, 如果这个进程退出了, 那么所有进程都会被kill。如果一个子进程的父进程退出了, 那么这个子进程会被挂到这个根进程下面。
  • linux又是以进程为最小执行单元的, 也就是说做任何事情都要依靠进程。从这里, 大家应该也能感觉到这个进程的重要性了

三、读取inittab

init进程在启动时会读取/etc/inittab, 接着根据该配置文件的启动层级和执行项来启动对应的程序。

以下的代码就是一个典型的inittab文件

# Default runlevel. The runlevels used by RHS are:
#   0 - halt (Do NOT set initdefault to this)
#   1 - Single user mode
#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
#   3 - Full multiuser mode
#   4 - unused
#   5 - X11
#   6 - reboot (Do NOT set initdefault to this)
# 
id:5:initdefault:

我们发现inittab文件其实很简单, 真正有用的其实就一行: id:5:initdefault

在讲解这一行代码前, 我们先介绍一下linux系统的运行级别, linux系统总共设置了7种运行级别, 不同的运行级别对应不同的执行方式。这7种运行级别分别是:

0级1级2级3级4级5级6级
关机单用户模式无网络的多用户模式多用户模式(无图形界面)未使用多用户模式(有图像界面)重启

以上的inittab文件表示init进程要启动的进程将会完成操作系统5级的功能。

四、执行系统初始化脚本(/etc/rc.d/rc.sysinit)

对linux系统一些必备的东西进行初始化, 比如时钟, 键盘, 磁盘, 文件系统等。

这个脚本比较长, 也比较复杂, 而且都是对系统级的操作, 没什么讲解的必要。就不讲解这个脚本的内容了。

五、执行启动层级对应的脚本(/etc/rc*.d)

linux系统不同的运行级别有不同的进程, 这些进程就要依靠这些脚本来启动。

比如: 在上面的例子中, /etc/inittab文件中记录的运行级别为: 5。所以, 由init进程执行/etc/rc5.d进程, 进行5运行级别必要的操作。

所以: 在早期, 如果有系统级的进程想要设置为开机启动, 就将启动该进程的命令放在该文件中。这种进程通常是一种服务, 至于什么是服务, 进程那里会详细讲解的后面有了service系统, 就不需要手动更改配置文件了。

六、不同的运行级别执行不同操作

例如: 对于3级, 5级来说, 就是启动对应的终端。5级为图形终端, 3级为命令行终端。然后执行rc.local文件。

所以: 早期如果有什么用户级进程需要在系统启动时自动启动, 就添加到rc.local文件中。 后面有了service系统, 就不需要手动更改配置文件了。

总结早期linux启动过程:

  • 完成开机自检到加载内核阶段
  • 启动init进程负责产生其它所有的用户进程
  • 读取inittab 并根据配置的启动层级和执行项来启动对应的程序
  • 执行系统初始化脚本(rc.sysinit)
  • 根据启动层级启动对应对应的脚本(rc*.d)

现代开机方式

现代的启动方式就是systemd系统。根据linux习惯, 字母d是守护(deamon)的缩写。systemd在名称上就是要守护整个linux系统的含义。

systemd系统极其庞大, 复杂。这里更多的是对systemd系统更多的是一个介绍 和 基本的设置。

systemd与早期的区别

一、启动的进程将不再是/etc/init进程, 而是/lib/systemd/systemd。
  • 我们使用命令 ps -ef | more 查看进程。看到pid为1的进程还是/sbin/init
  • 我们再使用命令ls -l /sbin/init输出/sbin/init -> /lib/systemd/systemd
  • 可以看到他只是个软链接罢了 真正pid为1的其实还是systemd进程
二、默认启动的系统级进程通过系统目录进行配置(代替/etc/inittab的配置方式)
优先级1级2级3级
配置目录/etc/systemd/system/run/systemd/system/lib/systemd/system

systemd根据优先级从高到低的从这些目录中读取配置文件。启动这些配置文件对应的进程。如果同一服务三个地方都配置了, 优先级高的会覆盖优先级低的。

  • 在安装好samba服务后, 系统会在/lib/systemd/system目录中添加一个默认的配置文件(smbd.service)。
  • 如果想自己设置配置文件, 只要在/etc/systemd/system目录下添加自定义的配置文件
  • 这样就将/lib/systemd/system目录下的配置文件覆盖掉了。
  • 至于/run/systemd/system是系统用来配置的, 我们不需要去管。
三、apt list
  • apt list:查看可以下载的所有包
  • apt list --installed:查看已经被下载的所有包
  • apt list --installed | grep samba:正则表达式查看被下载的相关samba包
  • apt list --installed 2> /dev/null | grep samba:重定向把error和warning扔到null里
四、重定向
重定向>>>2>
作用覆盖文件内容文件末尾追写只输入error和warining 剩下的原位置输出

systemd配置文件

现在大家只要知道一个服务的配置文件有三块就可以了, 具体表示什么, 如果之后用到了配置服务的情况, 再详细讲解。到时有了例子, 也好讲多了。

部分unit块service块install块
作用启动顺序与依赖关系启动行为定义如何安装这个配置文件, 即如何做到开机自启

systemd优势

systemed系统功能强大, 使用简单。systemd系统可以对这些配置文件按照固定的格式优化, 比如可以让多个服务同时启动, 大幅提高服务启动效率。

init系统配置文件中仅仅是些让脚本启动的命令, 脚本具体是什么格式完全由开发人员确定。这就导致整个系统难以优化, 各种服务只能线性的依次启动, 效率很低。

systemed系统组成

systemed系统 缺点就是体系庞大, 十分复杂

单元unitscopeslicesnapshotsocketswaptimer
作用路径不是由systemd启动的外部进程进程组systemd快照套接字文件交换
单元unitserveicetargetdevicemountautomountpath
作用服务运行级别设备文件系统的挂载点自动挂载点路径

当然不需要全部掌握, 否则东西太多了, 每一个 unit 知识点都很多。实际上我们只需要掌握 service 单元就可以了。

可以去百度一下 timer unittarget unit , 这两个网络配置时也是会用到的

systemctl 命令

systemctl 命令是 systemd 的主要命令, 可以用于管理服务单元。

  • systemctl enable httpd.service: 使某任务开机自启
  • systemctl disable httpd.service: 使某服务不开机自启
  • systemctl status httpd.service: 服务详细信息
  • systemctl list-units --type=service: 显示所有已经启动的服务
  • systemctl start httpd.service: 启动某服务
  • systemctl stop httpd.service: 停止某服务
  • systemctl restart httpd.service: 重启某服务