当前位置: 首页 > news >正文

Linux学习教程(第十六章 Linux系统启动管理)一

第十六章 Linux系统启动管理(一)

Linux 系统的启动是不需要人为参与和控制的,只要按下电源,系统就会按照设定好的方式进行启动。不过,了解系统的启动有助于我们在系统出现问题时能够快速地修复 Linux 系统。

在 CentOS 6.x 中,系统的启动过程和以前的系统相比变化较大,CentOS 6.x 系统使用 Upstart 启动服务取代了原先的 System V init 启动服务。Upstart 是事件驱动类型的,使用事件来启动和关闭系统服务;而 System V init 则基于运行级别的系统,使用运行级别和链接来启动和关闭系统服务。Upstart 启动方式比原先的 System V init 启动方式要更快速。

因此,虽然 CentOS 6.x 比 CentOS 5.x 更加庞大,但是 CentOS 6.x 的启动速度却快于 CentOS 5.x。

一、Linux系统启动流程(以CentOS 6为对象)

Linux 系统的启动,从计算机开机通电自检开始,一直到登陆系统,需要经历多个过程。学习 Linux 的启动过程,有助于了解 Linux 系统的结构,也对系统的排错有很大的帮助。

CentOS 6.x 系统启动过程发生了较大的变化,使用 Upstart 启动服务取代了原先的 System V init 启动服务。Upstart 启动服务的效率更高,启动速度更快。

Linux 系统启动过程比较复杂,我们先整理一下基本的启动过程,有一个整体的印象,然后再进一步说明。

目前,CentOS 6.x 的启动流程经历以下几步:

  1. 服务器加电,加载 BIOS 信息,BIOS 进行系统检测。依照 BIOS 设定,找到第一个可以启动的设备(一般是硬盘);
  2. 读取第一个启动设备的 MBR (主引导记录),加载 MBR 中的 Boot Loader(启动引导程序,最为常见的是 GRUB)。
  3. 依据 Boot Loader 的设置加载内核,内核会再进行一遍系统检测。系统一般会采用内核检测硬件的信息,而不一定采用 Bios 的自检信息。内核在检测硬件的同时,还会通过加载动态模块的形式加载硬件的驱动。
  4. 内核启动系统的第一个进程,也就是 /sbin/init。
  5. 由 /sbin/init 进程调用 /etc/init/rcS.conf 配置文件,通过这个配置文件调用 /etc/rc.d/rc.sysinit 配置文件。而 /etc/rc.d/rc.sysinit 配置文件是用来进行系统初始化的,主要用于配置计算机的初始环境。
  6. 还是通过 /etc/init/rcS.conf 配置文件调用 /etc/inittab 配置文件。通过 /etc/inittab 配置文件来确定系统的默认运行级别。
  7. 确定默认运行级别后,调用 /etc/init/rc.conf 配置文件。
  8. 通过 /etc/init/rc.conf 配置文件调用并执行 /etc/rc.d/rc 脚本,并传入运行级别参数。
  9. /etc/rc.d/rc 确定传入的运行级别,然后运行相应的运行级别目录 /etc/rc[0-6].d/ 中的脚本。
  10. /etc/rc[0-6].d/ 目录中的脚本依据设定好的优先级依次启动和关闭。
  11. 最后执行 /etc/rc.d/rc.local 中的程序。
  12. 如果是字符界面启动,就可以看到登录界面了。如果是图形界面启动,就会调用相应的 X Window 接口。

  • 总的来说,Linux 系统的启动,要经历BIOS自检 -> 启动 GRUB -> 加载内核 -> 执行第一个进程 -> 配置系统初始环境。当然,本节仅是简单地看启动过程,接下来分别详解介绍每步启动过程。

二、Linux BIOS开机自检简介

前面提到,服务器通电后,会直接进入 BIOS,BIOS 全称 Basic Input/Output System,中文可译为基本输入/输出系统。

简单地理解 BIOS,它就是固化在主板上一个 ROM(只读存储器)芯片上的程序,主要保存计算机的基本输入/输出信息、系统设置信息、开机自检程和系统自启动程序,用来为 计算机提供最底层和最直接的硬件设置与控制。

也就是说,BIOS 是硬件与软件之间的接口,而且是非常基本的接口,BIOS 提供了一组基本的操作系统使用的指令,系统启动的成功与否,依赖于 BIOS。

BIOS 的初始化主要完成以下 3 项工作:

  1. 第一次检查计算机硬件和外围设备(第二次自检由内核完后,后续会讲),例如 CPU、内存、风扇灯。当 BIOS 一启动,就会做一个自我检测的工作,整个自检过程也被称为 POST(Power On Self Test)自检。
  2. 如果自检没有问题,BIOS 开始对硬件进行初始化,并规定当前可启动设备的先后顺序,选择由那个设备来开机。
  3. 选择好开启设备后,就会从该设备的 MBR(主引导目录)中读取 Boot Loader(启动引导程序)并执行。启动引导程序用于引导操作系统启动,Linux 系统中默认使用的启动引导程序是 GRUB。

当 MBR 被加载到 RAM 之后,BIOS 就会将控制权交给 MBR,进入系统引导的第二阶段。

三、主引导目录(MBR)结构及作用详解

MBR 也就是主引导记录,位于硬盘的 0 磁道、0 柱面、1 扇区中,主要记录了启动引导程序和磁盘的分区表。我们通过图 1 来看看 MBR 的结构。

图  1 MBR的结构

MBR 共占用了一个扇区,也就是 512 Byte。其中 446 Byte 安装了启动引导程序,其后 64 Byte 描述分区表,最后的 2 Byte 是结束标记。我们已经知道,每块硬盘只能划分 4 个主分区,原因就是在 MBR 中描述分区表的空间只有 64 Byte。其中每个分区必须占用 16 Byte,那么 64 Byte 就只能划分 4 个主分区。每个分区的 16 字节的规划如表 2 所示。

表 2 分区表内容

存储字节数据内容及含义
第 1 字节引导标志
第 2 字节本分区的起始磁道号
第 3 字节本分区的起始扇区号
第 4 字节本分区的起始柱面号
第 5 字节分区类型,可以识别主分区和扩展分区
第 6 字节本分区的结束磁道号
第 7 字节本分区的结束扇区号
第 8 字节本分区的结束柱面号
第 9~12 字节本分区之前已经占用的扇区数
第 13~16 字节本分区的总扇区数

大家注意到了吧,MBR 中最主要的功能就是存储启动引导程序。

启动引导程序的作用

BIOS 的作用就是自检,然后从 MBR 中读取出启动引导程序。那么,启动引导程序最主要的作用就是加载操作系统的内核。当然,每种操作系统的启动引导程序都是不同的。

每种操作系统的文件格式不同,因此,每种操作系统的启动引导程序也不一样。不同的操作系统只有使用自己的启动引导程序才能加载自己的内核。如果我的服务器上只安装了一个操作系统,那么这个操作系统的启动引导程序就会安装在 MBR 中。BIOS 调用 MBR 时读取出启动引导程序,就可以加载内核了。

但是在有些时候,我的服务器中安装了多个操作系统,而 MBR 只有一 个,那么在 MBR 中到底安装哪个操作系统的启动引导程序呢?

很明显,一个 MBR 是不够用的。每块硬盘只能有一个 MBR 是不能更改的,所以不可能増加 MBR 的数量。系统只能在每个文件系统(可以看成分区)中单独划分出一个扇区,称作引导扇区(Boot Sector)。每个分区的引导扇区中也能安装启动引导程序,也就是说,在 MBR 和每个单独分区的引导扇区中都可以安装启动引导程序。这样多个操作系统才能安装在同一台服务器中(每个操作系统要安装在不同的分区中),而且每个操作系统都是可以启动的。

还有一个问题,BIOS 只能找到 MBR 中的启动引导程序,而找不到在分区的引导扇区中的启动引导程序。那么,要想完成多系统启动,我们的方法是増加启动引导程序的功能,让安装到 MBR 中的启动引导程序(GRUB)可以调用在分区的引导扇区中的其他启动引导程序。

因此,启动引导程序拥有以下功能:

  1. 加载操作系统的内核。这是启动引导程序最主要的功能。
  2. 拥有一个可以让用户选择的菜单,来选择到底启动哪个系统。大家如果在服务器上安装过双 Windows 系统,就应该见过类似的选择菜单,不过这个选择菜单是由 Windows 的启动引导程序提供的,而不是 GRUB。
  3. 可以调用其他的启动引导程序,这是多系统启动的关键。不过需要注意的是,Windows 的启动引导程序不能调用 Linux 的启动引导程序,所以我们一般建议先安装 Windows,后安装 Linux,是为了将 Linux 的启动引导程序安装到 MBR 中,覆盖 Windows 的启动引导程序。

当然,这个安装顺序不是绝对的,就算最后安装了 Windows,我们也可以通过手工再安装 GRUB 的方法,来保证 MBR 中安装的还是 Linux 的启动引导程序。

下图为我们展示了启动引导程序的作用。

图 2 启动引导程序的作用

四、Linux内核(内核模块)的加载过程

GRUB 加载了内核之后,内核首先会再进行二次系统的自检,而不一定使用 BIOS 检测的硬件信息。这时内核终于开始替代 BIOS 接管 Linux 的启动过程了。

内核完成再次系统自检之后,开始采用动态的方式加载每个硬件的模块,这个动态模块大家可以想象成硬件的驱动(默认 Linux 硬件的驱动是不需要手工安装的,如果是重要的功能,则会直接编译到内核当中;如果是非重要的功能,比如硬件驱动会编译为模块,则在需要时由内核调用。不过,如果没有被内核硬件,要想驱动,就需要手工安装个硬件的硬块了。具体的安装方法会在后续章节中介绍)。

那么,Linux 的内核到底放在了哪里呢?当然是 /boot 的启动目录中了,我们来看看这个目录下的内容吧。

[root@localhost ~]#ls /boot/
config-2.6.32-279.el6.i686
#内核的配置文件,内核编译时选择的功能与模块
efi
#可扩展固件接口,为英特尔为全新PC固件的体系结构、接口和服务提出的建议标准
grub
#启动引导程GTUB的数据目录
initramfe-2.6.32-279.el6.i686.img
#虚拟文件系统(CentOS 6.x 中用initramfs替代了initrd,但功能是一样的)
lost+found
故boot分区的备份目录
symvers-2_6.32-279.el6.i686.gz
#模块符号信息
System.map-2.6.32-279.el6.i686
#内核功能和内存地址的对应列表
vmlinuz-2.6.32-279.el6.i686
#用于启动的Linux内核。这个文件是一个压缩的内核镜像

我们已经知道,Linux 会把不重要的功能编译成内核模块,在需要时再调用,从而保证了内核不会过大。在多数 Linux 中,都会把硬件的驱动程序编译为模块, 这些模块保存在 /lib/modules 目录中。常见的 USB、SATA 和 SCSI 等硬盘设备的驱动,还有一些特殊的文件系统(如 LVM、RAID 等)的驱动,都是以模块的方式来保存的。

如果 Linux 安装在 IDE 硬盘之上,并且采用的是默认的 ext3/4 文件系统,那么内核启动后加载根分区和模块的加载都没有什么问题,系统会顺利启动。但是,如果 Linux 安装在 SCSI 硬盘之上,或者采用的是 LVM 文件系统,那么内核(内核载入内存是启动引导程序 GRUB 调用的,并不存在硬盘驱动不识别的问题)在加载根目录之前是需要加载 SCSI 硬盘或 LVM 文件系统的驱动的。

SCSI 硬盘和 LVM 文件系统的驱动都放在硬盘的 /lib/modules 目录中,既然内核没有办法识别 SCSI 硬盘或 LVM 文件系统,那怎么可能读取 /lib/modules 目录中的驱动呢?Linux 给出的解决办法是使用 initramfs 这个虚拟文件系统来处理这个问题。

initramfe虚拟文件系统

CentOS 6.x 中使用 initramfs 虚拟文件系统取代了 CentOS 5.x 中的 initrd RAM Disk。它们的作用类似,可以通过启动引导程序加载到内存中,然后会解压缩并在内存中仿真成一个根目录,并且这个仿真的文件系统能够提供一个可执行程序,通过该程序来加载启动过程中所需的内核模块,比如 USB、SATA. SCSI 硬盘的驱动和 LVM、RAID 文件系统的驱动。

也就是说,通过 initramfs 虚拟文件系统在内存中模拟出一个根目录,然后在这个模拟根目录中加载 SCSI 等硬件的驱动,就可以加载真正的根目录了,之后才能调用 Linux 的第一个进程 /sbin/init。

Initramfs 虚拟文件系统主要有以下优点:

  • initramfs 随着其中数据的増减自动増减容量。
  • 在 initramfs 和页面缓存之间没有重复数据。
  • initramfs 重复利用了 Linux caching 的代码,因此几乎没有増加内核尺寸,而 caching 的代码已经经过良好测试,所以 initramfs 的代码质量也有保证。
  • 不需要额外的文件系统驱动。

其实大家只需要知道 initramfs 是为了在内核中建立一个模拟根目录,这个模拟根目录是为了可以调用 USB、SATA、SCSI、LVM、RAID 等硬盘接口或文件系统的驱动模块,加载了驱动模块后才可以加载真正的系统根目录。我们可以通过示意图 1 来表示这个过程。

图 1 内核启动流程

那么既然 initramfs 是一个仿真根目录,那么我们是否可以看看这个仿真根目录中到底是什么样子的呢?当然可以,命令如下:

[root@localhost ~]# mkdir /tmp/initramfs
#建立测试目录
[root@localhost ~]# cp/boot/
initramfs-2.6.32-279.el6.i686.img/tmp/initramfs/
#复制initramfs文件
[root@localhost ~]# cd /tmp/initramfs/
[root@localhost initramfs]# file
initramfs-2.6.32-279.el6.i686.img
initramfe-2.6.32-279.el6.i686.img:gzip compressed
data,from Unix,last modified:
Wed Apr 10 21:49:34 2013, max compression
#查看文件类型,发现这个文件是一个使用gzip命令打包的压缩包
[root@localhost initramfs]# mv initramfs-2.6.32-279.el6.i686.imginitramfs-2.6.32-279.el6.i686.img.gz
#修改文件的扩展名为.gz
[root@localhost initramfs]# gunzip
initramfs-2.6.32-279.el6.i686.img.gz
#解压缩
[root@localhost initramfs]# ls
initramfs-2.6.32-279.el6.i686.img
[root@localhost initramfs]# file
initramfs-2.6.32-279.el6.i686.img
initramfe-2.6.32-279.el6.i686.img: ASCII cpio archive (SVR4withnoCRC)
#查看文件类型,使用cpio命令的压缩文件
[root@localhost initramfs]# cpio -ivcdu <initramfs-2.6.32-279.el6.i686.img
#解压缩
[root@localhost initramfs]#ll
总用量34512
drwxr-xr-x. 2 root root 4096 4月 2412:10 bin
drwxr-xr-x. 2 root root 4096 4 月 24 12:10 cmdline
drwxr-xr-x. 3 root root 4096 4月 24 12:10 dev
-rw-r--r--. 1 root root 19 4 月 24 12:10 dracut-004-283.el6
drwxr-xr-x. 2 root root 4096 4 月 24 12:10 emergency
drwxr-xr-x. 7 root root 4096 4月 24 12:10 etc
-rwxr-xr-x. 1 root root 8962 4月 24 12:10 init
drwxr-xr-x. 2 root root 4096 4 月 24 12:10 initqueue
drwxr-xr-x. 2 root root 4096 4 月 24 12:10 initqueue-finished
drwxr-xr-x. 2 root root 4096 4 月 24 12:10 initqueue-settled
drwxr-xr-x. 2 root root 4096 4 月 24 12:10
initqueue-timeout
-rw-r--r--. 1 root root 35235328 4 月 24 12:09 initramfs-2.6.32-279.el6.i686.img
drwxr-xr-x. 9 root root 4096 4月 2412:10 lib
…省略部分输出…
#这就是initramfs虚拟文件系统中的内容,和根目录是不是很像

五、Linux /sbin/init初始化系统环境

在内核加载完毕,并完成硬件检测与驱动程序加载后,此时主机硬件已经准备完毕,内核会主动呼叫第一个进程,也就是 /sbin/init,此配置文件最主要的功能就是准备软件执行的环境,包括系统的主机名、网络设定、语言、文件系统格式及其他服务的启动等。

这里和 CentOS 5.x 系统相比也有较大变化。在 CentOS 5.x 系统中,主要通过 init 进程的配置文件 /etc/inittab 来设定系统,并启动 Linux。但是在 CentOS 6.x 系统中,由于用 Upstart 启动服务来替换以前的 init,所以在 /etc/inittab 配置文件中只能定义系统的默认运行级别,而其他的功能是靠 /etc/init/ 目录中的其他配置文件实现的。

大家可以把 /etc/init/ 目录中的配置文件看成以前 /etc/inittab 这个文件功能的分拆。

本章开头提到,由 /sbin/init 进程可通过 /etc/init/rcS.conf 配置文件,分别找到 /etc/rc.d/rc.sysinit 配置文件和 /etc/inittab 配置文件,前者用于初始化系统,配置计算机的初始环境;后者用于确定系统的默认运行级别。

接下来,先介绍 /etc/rc.d/rc.sysinit 配置文件。如果我们使用 Vim 查看 /etc/rc.d/rc.sysinit 配置文件,就会发现这个这个配置文件主要进行了以下几项工作:

  • 获得网络环境和主机类型;
  • 测试设备:除了挂载内存设备 /proc 之外,还会主动侦测系统上是否具有 usb 设备,如果有,则会主动加载 usb 的驱动程序,并尝试挂载 usb 文件系统;
  • 开机启动画面 Plymouth(代替了以往的 RHGB);
  • 判断是否启用 SELinux;
  • 显示开机过程中的欢迎画面;
  • 初始化硬件;
  • 用户自定义模块的加载,用户可以在 /etc/sysconfig/modules/*.modules 加入自订的模块,则此时会被加载到系统当中;
  • 配置内核的参数,系统会主动去读取 /etc/sysctl.conf 这个文件的配置参数,使内核的功能成为我们想要的样子。
  • 设置主机名。
  • 同步存储器。
  • 设备映射器及相关的初始化。
  • 初始化软件磁盘阵列 (RAID)。
  • 初始化 LVM 的文件系统功能。
  • 检验磁盘文件系统 (fsck)。
  • 设置磁盘配额 (quota)。
  • 重新以可读写模式挂载系统磁盘。
  • 更新 quota (非必要)。
  • 启动系统虚拟随机数生成器。
  • 配置机器(非必要)。
  • 清除开机过程中的临时文件。
  • 创建 ICE 目录。
  • 启动交换分区(swap)。
  • 将开机信息写入 /var/log/dmesg 文件中。

在以上过程中,比较值得注意的是自定模块的加载。在 CentOS 中,如果我们想要加载核心模块的话,就可以将整个模块写入到 /etc/sysconfig/modules/*.modules 中。当然,此过程并不是必须的,通常我们的默认模块已经够用,除非对硬件太新,不得不自己加载模块,否则无需刻意添加任何模块。

可以看到,/etc/rc.d/rc.sysinit 配置文件已经将基本的系统配置数据都写好了,我们可以查询 /var/log/dmesg 文件或使用 dmesg 命令查看系统在启动时到底发生了什么。当然,我们也可以通过这个命令来看看 Linux 服务器的硬件信息。

有关 /etc/inittab 配置文件的内容,放到了下节进行详细介绍。

六、Linux /etc/inittab:设置(修改)系统默认运行级别

在 CentOS 6.x 中,/etc/inittab 配置文件只能用来设置系统的默认运行级别。

那么,什么是运行级别呢?其实 Linux 是通过运行级别来确定系统启动时到底启动哪些服务的。Linux 默认有 7 个运行级别,具体如表 1 所示。

表 1 运行级别

运行级别含 义
0关机
1单用户模式,可以想象为 Windows 的安全模式,主要用于系统修复
2不完全的命令行模式,不含 NFS 服务
3完全的命令行模式,就是标准字符界面
4系统保留
5图形模式
6重新启动

在 Linux 系统中可以使用 runlevel 命令来查看系统的运行级别,命令如下:

[root@localhost ~]# runlevel
N 3
#N代表在进入这个级别前,上一个级别是什么;3代表当前级别

在这个命令的结果中,"N 3"中的N代表在进入这个级别前,上一个级别是什么;3 代表当前级别。"N" 就是 None 的意思,也就是说,系统是开机直接进入 3 运行级别的,没有上一个运行级别。那如果从图形界面切换到字符界面,再查看运行级别,就应该是这样的:

[root@localhost ~]# runlevel
5 3
#代表由5级别进入3级别

那么,可以手工改变当前的运行级别吗?当然可以了,只需使用 init 命令(注意这不是 init 进程)即可,命令如下:

[root@localhost ~]# init 5
#进入图形界面,当然要已经安装了图形界面才可以
[root@localhost ~]# init 0
#关机
[root@localhost ~]# init 6
#重新启动

不过要注意,使用 init 命令关机和重启并不是太安全,容易造成数据丟失。所以推荐大家使用 shutdown 命令进行关机和重启。

系统默认运行级别

知道了运行级别的作用,我们回到系统启动过程中来。/etc/inittab 配置文件的功能就是确定系统的默认运行级别,也就是系统开机后会进入那个运行级别。此文件的内容如下:

[root@localhost ~]#vim /etc/inittab
# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#系统会先调用/etc/init/rcS.conf
# Individual runlevels are started by /etc/init/rc.conf
#在调用/etc/init/rc.conf,在不同的运行级别启动不同的服务
# Ctrl-Alt-Delete is handled by/etc/init/control-alt-delete.conf
#通过这个配置文件判断Ctri+Alt+Delete热启动键是否可用
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#判断系统可以启动的本地终端数量及终端的基本设置(如颜色)
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used 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)
#很眼熟吧,就是刚刚的 0~6运行级别的说明
id:3:initdefault:
#这就是系统的默认运行级别,也就是系统开机后直接进入哪个运行级别

注意,这里的默认运行级别只能写 3 或 5,其他的级别要么是关机重启,要么是保留或单用户,都不能作为系统默认运行级别。

七、Linux /etc/rc.d/rc.local配置文件用法

在 /etc/rc[06].d/ 目录中的程序启动之后,系统的启动就已经完成。不过,我们总有一些程序是需要在系统启动之后随着系统一起启动的。这时我们并不需要自己把需要启动的服务链接到 /etc/rc3.d/ 目录中,因为系统给我们准备了 /etc/rc.d/rc.local 配置文件。

这个配置文件会在用户登陆之前读取,这个文件中写入了什么命令,在每次系统启动时都会执行一次。也就是说,如果有任何需要在系统启动时运行的工作,则只需写入 /etc/rc.d/rc.local 配置文件即可。这个文件的内容如下:

[root@localhost ~]# ll /etc/rc.local
Irwxrwxrwx. 1 root root 13 4月10 21:46 /etc/rc.local -> rc.d/rc.local
#有一个链接文件,两个文件修改哪一个都可以
[root@localhost ~]#vi /etc/rc.d/rc.local
#!/bin/sh
#
#This script will be executed *after* all the other init scripts.
#You can put your own initialization stuff in here if you don't
#want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
#默认会touch这个文件,每次系统启动时都会touch这个文件,这个文件的修改时间就是系统的启动时间
/etc/rc.d/init.d/httpd start
#如果写入RPM包安装的apache服务的启动命令,apache服务就会在开机时自动启动

Linux 的启动过程基本上就是这样的,我们把启动流程图补充完整,如图 1 所示。

图 1 Linux启动流程

系统的启动过程就是这样的,最终我们就能登录字符界面的 Linux 了。不过,如果需要启动图形界面的 Linux,则还需要调用 X Window 接口。

在启动过程中还有一个配置文件会生效,就是 /etc/init/start-ttys.conf,这个文件主要定义了 Linux 支持的 1~6 个本地终端(tty[1-6])。如果在本机,则可以使用快捷键 Alt+F1~F6 来切换这 6 个本地终端;如果安装并启动了图形界面,则可以使用快捷键 Ctrl+Alt+F7 来切换图形终端。

至此,字符界面的启动过程就介绍完了。是不是非常复杂?如果你是初学者,则只需了解,不需要彻底掌握。但是掌握了 Linux 系统的启动过程,会更加了解 Linux 的结构。当然,如果你非常自信,则可以尝试安装 gentoo Linux 这个版本,因为这个 Linux 版本到目前为止还是纯源码安装的,如果能够安装成功,就会对 Linux 系统的结构及启动过程有更深入的理解。

八、Linux启动引导程序(GRUB)加载内核的过程

在刚刚的启动过程中,我们已经知道启动引导程序(Boot Loader,也就是 GRUB)会在启动过程中加载内核,之后内核才能取代 BIOS 接管启动过程。如果没有启动引导程,那么内核是不能被加载的。

本节,我们就来看看启动引导程序加载内核的过程,当然 initramfs 这个虚拟文件系统也是要靠启动引导程序调用的。在 CentOS 6.x 中,启动引导程序默认是 GRUB,GRUB 是现在最为流行的启动引导程序,我们也用 GRUB 来说明启动引导程序的作用。

早期的 LILO 引导程序已经不是很常见了,GRUB 相比来讲有很多优势,主要有:

  • 支持更多的文件系统。
  • GRUB 的主程序可以直接在文件系统中查找内核文件。
  • 在系统启动时,可以利用 GRUB 的交互界面编辑和修改启动选项。
  • 可以动态修改 GRUB 的配置文件,这样在修改配置文件之后不需要重新安装 GRUB,而只需重新启动就可以生效。

GRUB加载内核的过程

GRUB 的作用有以下几个:

  • 加载操作系统的内核;
  • 拥有一个可以让用户选择的的菜单,来选择到底启动哪个系统;
  • 可以调用其他的启动引导程序,来实现多系统引导。

按照启动流程,BIOS 在自检完成后,会到第一个启动设备的 MBR 中读取 GRUB。在 MBR 中用来放置启动引导程序的空间只有 446 Byte,那么 GRUB 可以放到这里吗?答案是空间不够,GRUB 的功能非常强大,MBRM 空间是不够使用的。那么 Linux 的解决办法是把 GRUB 的程序分成了三个阶段来执行。

(1)Stage 1:执行GRUB主程序

第一阶段是用来执行 GRUB 主程序的,这个主程序必须放在启动区中(也就是 MBR 或者引导扇区中)。但是 MBR 太小了,所以只能安装 GRUB 的最小的主程序,而不能安装 GRUB 的相关配置文件。这个主程序主要是用来启动 Stage 1.5 和 Stage 2 的。

(2)Stage 1.5:识别不同的文件系统

Stage 2 比较大,只能放在文件系统中(分区),但是 Stage 1 不能识别不同的文件系统,所以不能直接加载 Stage 2。这时需要先加载 Stage 1.5,由 Stage 1.5 来加载不同文件系统中的 Stage 2。

还有一个问题,难道 Stage 1.5 不是放在文件系统中的吗?如果是,那么 Stage 1 同样不能找到 Stage 1.5。其实,Stage 1.5 还真没有放在文件系统中,而是在安装 GRUB 时,直接安装到紧跟 MBR 之后的 32KB 的空间中,这段硬盘空间是空白无用的,而且是没有文件系统的,所以 Stage 1 可以直接读取 Stage 1.5。读取了 Stage 1.5 就能识别不同的文件系统,才能加载 Stage 2。

(3)Stage 2:加载GRUB的配置文件

Stage 2 阶段主要就是加载 GRUB 的配置文件 /boot/grub/grub.conf,然后根据配置文件中的定义,加载内核和虚拟文件系统。接下来内核就可以接管启动过程,继续自检与加载硬件模块了。

相关文章:

  • 云呼叫中心支持的通信渠道
  • 对curl,git,python添加proxy的方法
  • NCL : S7-200 SMART 库源代码分享
  • Mac设置ll永久生效,设置.bash_profile生效
  • 3D模型人物换装系统(三 优化合批处理,提取合批配置可,封装)
  • 【C语言刷题每日一题#牛客网BC69】——空心正方形图案
  • [RK-Linux] RK3399支持M.2 NVMe SSD启动
  • 【数据结构】迷宫问题报告+源码C/C++
  • 软件渗透测试有哪些测试流程?权威安全测试报告的重要性
  • Spring Boot学习随笔- 拦截器实现和配置(HandlerInterceptor、addInterceptors)、jar包部署和war包部署
  • 深信服技术认证“SCSA-S”划重点:命令执行漏洞
  • ubuntu20.04.3
  • 【Chrome】ERR_SSL_PROTOCOL_ERROR问题
  • redis基本用法学习(C#调用NRedisStack操作redis)
  • idea SpringBoot项目 Run Dashboard 多个启动类分组展示 失效
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • DOM的那些事
  • HomeBrew常规使用教程
  • JavaScript创建对象的四种方式
  • PaddlePaddle-GitHub的正确打开姿势
  • React-redux的原理以及使用
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • vuex 学习笔记 01
  • 对象管理器(defineProperty)学习笔记
  • 回流、重绘及其优化
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 温故知新之javascript面向对象
  • Prometheus VS InfluxDB
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • !$boo在php中什么意思,php前戏
  • # include “ “ 和 # include < >两者的区别
  • (BFS)hdoj2377-Bus Pass
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (NSDate) 时间 (time )比较
  • (pytorch进阶之路)扩散概率模型
  • (二)PySpark3:SparkSQL编程
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (分布式缓存)Redis分片集群
  • (力扣)1314.矩阵区域和
  • (五)IO流之ByteArrayInput/OutputStream
  • (一)SpringBoot3---尚硅谷总结
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (转)Scala的“=”符号简介
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .NET Core 成都线下面基会拉开序幕
  • .NET Core 项目指定SDK版本
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .NET 指南:抽象化实现的基类
  • .NET框架
  • /var/log/cvslog 太大
  • @AliasFor注解
  • [ 常用工具篇 ] POC-bomber 漏洞检测工具安装及使用详解