第20章、开机流程、模块管理与 Loader

20.1. Linux 的开机流程分析
开机不是只要单击电源钮而关机只要关掉电源钮就可以了吗?有何大学问?话是这样没错,但是由于 Linux 是一套多人多任务的操作系统,你难保你在关机时没有人还在线,如果你关机的时候碰巧一大群人在在线工作, 那会让当时在在线工作的人马上断线的!那不是害死人了?一些数据可是无价之宝!
另外 Linux 在执行的时候,虽然你在画面上只会看到黑压压的一片,完全没有任何画面, 但其实他是有很多的程序在背景底下执行的,例如登录文件管控程序、前面提到的例行性工作排程等, 当然还有一大堆网络服务,如邮件服务器、WWW 服务器等等。你如果随便关机的话, 是很容易伤害硬盘及数据传输的动作的!所以在 Linux 下关机可是一门大学问。

20.1.1. 开机流程一览
既然开机是很严肃的一件事,那我们就来了解一下整个开机的过程吧! 好让大家比较容易发现开机过程里面可能会发生问题的地方,以及出现问题后的解决之道! 不过,由于开机的过程中,那个开机管理程序 (Boot Loader) 使用的软件可能不一样,例如目前各大 Linux distributions 的主流为 grub,但早期 Linux 预设是使用 LILO ,台湾地区则很多朋友喜欢使用 spfdisk 。 但无论如何,我们总是得要了解整个 boot loader 的工作情况,才能了解为何进行多重引导的设定时, 老是听人家讲要先安装 Windows 再安装 Linux 的原因~
假设以个人计算机架设的 Linux 主机为例 (先回到第零章计算器概论看看相关的硬件常识), 当你按下电源按键后计算机硬件会主动的读取 BIOS 来加载硬件信息及进行硬件系统的自我测试, 之后系统会主动的去读取第一个可开机的装置 (由 BIOS 设定的) ,此时就可以读入开机管理程序了。
开机管理程序可以指定使用哪个核心档案来开机,并实际加载核心到内存当中解压缩与执行, 此时核心就能够开始在内存内活动,并侦测所有硬件信息与加载适当的驱动程序来使整部主机开始运作, 等到核心侦测硬件与加载驱动程序完毕后,一个最阳春的操作系统就开始在你的 PC 上面跑了。
主机系统开始运作后,此时 Linux 才会呼叫外部程序开始准备软件执行的环境, 并且实际的加载所有系统运作所需要的软件程序!最后系统就会开始等待你的登入与操作! 简单来说,系统开机的经过可以汇整成底下的流程的:

  1. 加载 BIOS 的硬件信息与进行自我测试,并依据设定取得第一个可开机的装置;
  2. 读取并执行第一个开机装置内 MBR 的 boot Loader (亦即是 grub, spfdisk 等程序);
  3. 依据 boot loader 的设定加载 Kernel ,Kernel 会开始侦测硬件与加载驱动程序;
  4. 在硬件驱动成功后,Kernel 会主动呼叫 init 程序,而 init 会取得 run-level 信息;
  5. init 执行 /etc/rc.d/rc.sysinit 档案来准备软件执行的作业环境 (如网络、时区等);
  6. init 执行 run-level 的各个服务之启动 (script 方式);
  7. init 执行 /etc/rc.d/rc.local 档案;
  8. init 执行终端机仿真程序 mingetty 来启动 login 程序,最后就等待用户登入;

大概的流程就是上面写的那个样子,你会发现 init 这个家伙占的比重非常重! 所以我们才会在第十七章的 pstree 指令中谈到这家伙。 那每一个程序的内容主要是在干嘛呢?底下就分别来谈一谈吧!

20.1.2. BIOS, boot loader 与 kernel 载入
我们在第三章曾经谈过简单的开机流程与 MBR 的功能, 当时为了多重引导而进行的简短的介绍。现在你已经有足够的 Linux 基础了,所以底下让我们来加强说明!

一、BIOS, 开机自我测试与 MBR
我们在第零章的计算器概论就曾谈过计算机主机架构, 在个人计算机架构下,你想要启动整部系统首先就得要让系统去加载 BIOS (Basic Input Output System),并透过 BIOS 程序去加载 CMOS 的信息,并且藉由 CMOS 内的设定值取得主机的各项硬件配置, 例如 CPU 与接口设备的沟通频率、开机装置的搜寻顺序、硬盘的大小与类型、 系统时间、各周边总线的是否启动 Plug and Play (PnP, 即插即用装置) 、 各接口设备的 I/O 地址、以及与 CPU 沟通的 IRQ 岔断等等的信息。
在取得这些信息后,BIOS 还会进行开机自我测试 (Power-on Self Test, POST) (注1)。 然后开始执行硬件侦测的初始化,并设定 PnP 装置,之后再定义出可开机的装置顺序, 接下来就会开始进行开机装置的数据读取了 (MBR 相关的任务开始)。
由于我们的系统软件大多放置到硬盘中!所以 BIOS 会指定开机的装置好让我们可以读取磁盘中的操作系统核心档案。 但由于不同的操作系统他的文件系统格式不相同,因此我们必须要以一个开机管理程序来处理核心档案加载 (load) 的问题, 因此这个开机管理程序就被称为 Boot Loader 了。那这个 Boot Loader 程序安装在哪里呢?就在开机装置的第一个扇区 (sector) 内,也就是我们一直谈到的 MBR (Master Boot Record, 主要启动记录区)。
那你会不会觉得很奇怪啊?既然核心档案需要 loader 来读取,那每个操作系统的 loader 都不相同, 这样的话 BIOS 又是如何读取 MBR 内的 loader 呢?很有趣的问题吧!其实 BIOS 是透过硬件的 INT 13 中断功能来读取 MBR 的,也就是说,只要 BIOS 能够侦测的到你的磁盘 (不论该磁盘是 SATA 还是 IDE 接口),那他就有办法透过 INT 13 这条信道来读取该磁盘的第一个扇区内的 MBR !(注2) 这样 boot loader 也就能够被执行!

二、Boot Loader 的功能
刚刚说到 Loader 的最主要功能是要认识操作系统的文件格式并据以加载核心到主存储器中去执行。 由于不同操作系统的文件格式不一致,因此每种操作系统都有自己的 boot loader !用自己的 loader 才有办法载入核心档案嘛!那你应该有听说过多重操作系统吧? 既然你 (1)必须要使用自己的 loader 才能够加载属于自己的操作系统核心,而 (2)系统的 MBR 只有一个,那你怎么会有办法同时在一部主机上面安装 Windows 与Linux 呢?
这就得要回到第八章的磁盘文件系统去回忆一下文件系统功能了。 其实每个文件系统 (filesystem, 或者是 partition) 都会保留一块启动扇区 (boot sector) 提供操作系统安装 boot loader , 而通常操作系统默认都会安装一份 loader 到他根目录所在的文件系统的 boot sector 上。如果我们在一部主机上面安装 Windows 与 Linux 后,该 boot sector, boot loader 与 MBR 的相关性会有点像下图:
这里写图片描述
如上图所示,每个操作系统默认是会安装一套 boot loader 到他自己的文件系统中 (就是每个 filesystem 左下角的方框),而在 Linux 系统安装时,你可以选择将 boot loader 安装到 MBR 去,也可以选择不安装。 如果选择安装到 MBR 的话,那理论上你在 MBR 与 boot sector 都会保有一份 boot loader 程序的。 至于Windows 安装时,他预设会主动的将 MBR 与 boot sector 都装上一份 boot loader !所以你会发现安装多重操作系统时,你的 MBR 常常会被不同的操作系统的 boot loader 所覆盖!
我们刚刚提到的两个问题还是没有解决!虽然各个操作系统都可以安装一份 boot loader 到他们的 boot sector 中, 这样操作系统可以透过自己的 boot loader 来加载核心了。问题是系统的 MBR 只有一个! 你要怎么执行 boot sector 里面的 loader ?这个我们得要回忆一下第三章约略提过的 boot loader 的功能了。boot loader 主要的功能如下:

  • 提供选单:用户可以选择不同的开机项目,这也是多重引导的重要功能!
  • 载入核心档案:直接指向可开机的程序区段来开始操作系统;
  • 转交其他 loader:将开机管理功能转交给其他 loader 负责。

由于具有选单功能,因此我们可以选择不同的核心来开机。而由于具有控制权转交的功能,因此我们可以加载其他 boot sector 内的 loader !不过 Windows 的 loader 预设不具有控制权转交的功能,因此你不能使用 Windows 的 loader 来加载 Linux 的 loader !这也是为啥第三章谈到 MBR 与多重引导时,会特别强调先装 Windows 再装 Linux 的缘故。 我们将上述的三个功能以底下的图标来解释你就看的懂了!(与第三章的图示也非常类似!)
这里写图片描述
如上图所示,我的 MBR 使用 Linux 的 grub 这个开机管理程序,并且里面假设已经有了三个选单, 第一个选单可以直接指向 Linux 的核心档案并且直接加载核心来开机;第二个选单可以将开机管理程控权交给 Windows 来管理,此时 Windows 的 loader 会接管开机流程,这个时候他就能够启动 windows 了。第三个选单则是使用 Linux 在 boot sector 内的开机管理程序,此时就会跳出另一个 grub 的选单!了解了吗?
而最终 boot loader 的功能就是『加载 kernel 档案』!

三、加载核心侦测硬件与 initrd 的功能
当我们藉由 boot loader 的管理而开始读取核心档案后,接下来, Linux 就会将核心解压缩到主存储器当中, 并且利用核心的功能,开始测试与驱动各个周边装置,包括储存装置、CPU、网络卡、声卡等等。 此时 Linux 核心会以自己的功能重新侦测一次硬件,而不一定会使用 BIOS 侦测到的硬件信息!也就是说,核心此时才开始接管 BIOS 后的工作了。 那么核心档案在哪里啊?一般来说,他会被放置到 /boot 里面,并且取名为 /boot/vmlinuz 才对!
这里写图片描述
从上表我们也可以知道此版本的 Linux 核心为 2.6.18-92.el5 这个版本!为了硬件开发商与其他核心功能开发者的便利, 因此 Linux 核心是可以透过动态加载核心模块的 (就请想成驱动程序即可),这些核心模块就放置在 /lib/modules/ 目录内。 由于模块放置到磁盘根目录内 (要记得 /lib 不可以与 / 分别放在不同的 partition !), 因此在开机的过程中核心必须要挂载根目录,这样才能够读取核心模块提供加载驱动程序的功能。 而且为了担心影响到磁盘内的文件系统,因此开机过程中根目录是以只读的方式来挂载的。
一般来说,非必要的功能且可以编译成为模块的核心功能,目前的 Linux distributions 都会将他编译成为模块。 因此 USB, SATA, SCSI… 等磁盘装置的驱动程序通常都是以模块的方式来存在的。 现在来思考一种情况,假设你的 linux 是安装在 SATA 磁盘上面的,你可以透过 BIOS 的 INT 13 取得 boot loader 与 kernel 档案来开机,然后 kernel 会开始接管系统并且侦测硬件及尝试挂载根目录来取得额外的驱动程序。
问题是,核心根本不认识 SATA 磁盘,所以需要加载 SATA 磁盘的驱动程序, 否则根本就无法挂载根目录。但是 SATA 的驱动程序在 /lib/modules 内,你根本无法挂载根目录又怎么读取到 /lib/modules/ 内的驱动程序?是吧!非常的两难吧!在这个情况之下,你的 Linux 是无法顺利开机的! 那怎办?没关系,我们可以透过虚拟文件系统来处理这个问题。
虚拟文件系统 (Initial RAM Disk) 一般使用的档名为 /boot/initrd ,这个档案的特色是,他也能够透过 boot loader 来加载到内存中, 然后这个档案会被解压缩并且在内存当中仿真成一个根目录, 且此仿真在内存当中的文件系统能够提供一支可执行的程序,透过该程序来加载开机过程中所最需要的核心模块, 通常这些模块就是 USB, RAID, LVM, SCSI 等文件系统与磁盘接口的驱动程序 !等载入完成后, 会帮助核心重新呼叫 /sbin/init 来开始后续的正常开机流程。
这里写图片描述
如上图所示,boot loader 可以加载 kernel 与 initrd ,然后在内存中让 initrd 解压缩成为根目录, kernel 就能够藉此加载适当的驱动程序,最终释放虚拟文件系统,并挂载实际的根目录文件系统, 就能够开始后续的正常开机流程。更详细的 initrd 说明,你可以自行使用 man initrd 去查阅看看。 底下让我们来了解一下 CentOS 5.x 的 initrd 档案内容有什么吧!
这里写图片描述
这里写图片描述
透过上述执行档的内容,我们可以知道 initrd 有加载模块并且尝试挂载了虚拟文件系统。 接下来就能够顺利的运作!那么是否一定需要 initrd 呢?
这里写图片描述
在核心完整的加载后,您的主机应该就开始正确的运作了,接下来,就是要开始执行系统的第一支程序: /sbin/init。

20.1.3. 第一支程序 init 及配置文件 /etc/inittab 与 runlevel
在核心加载完毕、进行完硬件侦测与驱动程序加载后,此时你的主机硬件应该已经准备就绪了 (ready) , 此时核心会主动的呼叫第一支程序,那就是 /sbin/init 。这也是为啥第十七章的 pstree 指令介绍时,你会发现 init 的 PID 号码是一号。 /sbin/init 最主要的功能就是准备软件执行的环境,包括系统的主机名、网络设定、语系处理、文件系统格式及其他服务的启动等。 而所有的动作都会透过 init 的配置文件,亦即是 /etc/inittab 来归划,而 inittab 内还有一个很重要的设定项目,那就是默认的 runlevel (开机执行等级) !

一、Run level:执行等级有哪些?
Linux 就是藉由设定 run level 来规定系统使用不同的服务来启动,让 Linux 的使用环境不同。基本上,依据有无网络与有无 X Window 而将 run level 分为 7 个等级,分别是:

  • 0 - halt (系统直接关机)
  • 1 - single user mode 单人维护模式,用在系统出问题时的维护)
  • 2 - Multi-user, without NFS (类似底下的 runlevel 3,但无 NFS 服务)
  • 3 - Full multi-user mode (完整含有网络功能的纯文本模式)
  • 4 - unused (系统保留功能)
  • 5 - X11 (与 runlevel 3 类似,但加载使用 X Window)
  • 6 - reboot (重新启动)

由于 run level 0, 4, 6 不是关机、重新启动就是系统保留的,所以:『 您当然不能将预设的 run level 设定为这三个值 』, 否则系统就会不断的自动关机或自动重新启动…. 好了,那么我们开机时,到底是如何取得系统的 run level 的?当然是 /etc/inittab 所设定的! 那么 /etc/inittab 到底有什么信息呢?我们先来看看这个档案的内容好了:

二、/etc/inittab 的内容与语法
这里写图片描述
这里写图片描述
首先,这个档案的语法是利用冒号 (:) 将设定分隔成为四个字段,每个字段的意义与说明如下:
这里写图片描述

  1. 设定项目:最多四个字符,代表 init 的主要工作项目,只是一个简单的代表说明。
  2. run level:该项目在哪些 run level 底下进行的意思。如果是 35 则代表 runlevel 3 与 5 都会执行。
  3. init 的动作项目:主要可以进行的动作项目意义有:
    这里写图片描述
  4. 更多的设定项目请参考 man inittab 的说明。
  5. 指令项目:亦即应该可以进行的指令,通常是一些 script 。

三、init 的处理流程
事实上 /etc/inittab 的设定也有点类似 shell script ,因为该档案内容的设定也是一行一行的从上往下处理的, 因此我们可以知道 CentOS 的 init 依据 inittab 设定的处理流程会是:

  1. 先取得 runlevel 亦即默认执行等级的相关等级 (以我的测试机为例,为 5 号);
  2. 使用 /etc/rc.d/rc.sysinit 进行系统初始
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值