在linux系统中的开机引导过程与关机过程。
Bootstrapping(引导) 是 Staring up a computer 的标准术语。 操作系统所提供的正常功能在启动过程中还不能使用,因此,计算机必须“通过其引导程序让自己启动起来”。 在引导过程中,内核被加载到内存中并开始执行。
各种初始化任务得以执行之后,用户就能够使用系统了。
引导阶段是系统特别脆弱的一段时间。
配置文件中的错误,丢失设备或者设备不可靠,以及受损的文件系统都会妨碍计算机的启动。
当打开计算机时,计算机执行存储在ROM中的引导代码,这些代码接下来尝试确定如何加载并启动内核。 内核检测系统的硬件,然后产生系统的init 进程,这个进程进程总是PID1.
在出现登陆提示符之前,要完成几项工作。
系统必须检查并安装文件系统,而且系统的守护进程必须启动起来,这些步骤是由init 进程按顺序运行一系列shell 脚本来管理的。
启动脚本由于它们的命名方式而经常被称作“rc文件”,rc 代表runcom 或者 run command。 启动脚本的确切位置以及它们执行方式随操作系统的不同而异。
一.自动引导和手工引导
Linux 系统即可以以自动方式也可以以手工方式来引导。 在自动方式下,系统自己执行全部引导过程,不需要任何外部的帮助。 在手工方式下,系统先自动执行一些过程,然后到某一个时刻后,在运行大多数初始化脚本以前,把控制权交给操作员。
在这时候,计算机处于“单用户模式”,大多数系统进程还没有运行,其他用户还不能够登陆系统。
二.引导过程的步骤
linux系统典型的引导过程由下面6个不同的阶段组成:
(1)加载并初始化内核
(2)检测和配置设备
(3)创建内核线程
(4)操作员干预(仅用于手工引导)
(5)执行系统启动脚本
(6)多用户模式运行
2.1 初始化内核
linux 内核本身就是一个程序,系统引导过程中的第一项任务就是把这个程序载入内存,以便执行它。 内核的路径名通常是/vmlinuz 或者 /boot/vmlinuz。
linux 系统实现了一种有两个阶段的加载过程。 在第一个阶段,系统rom把一个小的引导程序从磁盘载入到内存中。 然后这个程序再安排载入内核。
内核执行内存检测来确定有多少ram可用。 内核的一些内部数据结构按静态方式分配其内存量,因此,当内核启动时,它就为自己划分出一块固定大小的实存空间。 这块空间保留给内核使用。 用户级进程不能使用。 内核在控制台上打印一条消息,报告物理内存的总量以及用户进程可用的内存量。
2.2 配置硬件
内核执行的第一批任务之一包括检查机器的环境以确定机器有什么硬件。 当为自己的系统构建内核时,要告诉内核,它会找到哪些硬件设备。 当内核开始执行时,它视图找到并初始化已经告诉它的每一个设备。 大多数内核为他们所找到的每个设备打印出一行专门信息。 现在的发行版本所包含的内核能够在绝大多数机器配置上运行。
在内核配置期间提供的设备信息经常不够明确。 在这样的情况下,内核通过探测设备总线和向适当的驱动程序寻求信息来尝试确定它所需要的其他信息。 那些没有检测到设备的驱动程序或者哪些没有响应探测的驱动程序将被禁用。 如果某个设备后来被连接到系统上,那么还是有可能随时加载或者启用它的驱动程序的。
2.3 内核线程
一旦完成了基本的初始化任务,内核就在用户空间创建几个“自发”的进程。 因为这些进程不是通过系统正规的fork 机制所创建的。
自发进程的数量和特性随系统的不同而不同。 在linux 上,看不到有pid 0 进程。 和进程init(一定是进程1)一起的是几个内存和内核处理进程,包括下表列出的进程。 这些进程的PID都比较小。 在ps 命令的输出中他们的名字都被中括号括了起来,如:[kacpid]。 有时候这些进程的名字以一个斜线加一个数字结尾,比如[kblockd/0]。 这个数字表明该线程在哪个处理器上运行,在多处理器的系统上会出现这种现象。
Linux 内核进程
在所有这些进程中,只有init 是真正完成的用户进程。 其他进程实际上都是内核的组成部分,为了调度或者结构上的原因进行了装扮,使它们看上去像是进程而已。
一旦创建完毕自发进程,内核在引导阶段的任务就完成了。 不过,处理基本操作(比如接收登陆)的进程还一个都没有创建,而且大多数Linux 守护进程也都没有启动。 这些任务都是由init来负责的(有些情况是间接的)。
2.4 操作员干预(仅限手工引导)
如果系统以单用户模式进行引导,那么在init 启动时,内核所给出的命令行标志(single)会通知init 实际要引导的用户是单用户模式。 进程init 最后会把控制权交给sulogin,后者是login 的一个“中间件不可控”的特殊版本,它提示用户输入root口令。 如果输入的口令正确,系统将产生一个root shell。 用户可以按下<Control + D> 而不是输入口令来绕过单用户模式而继续进入到多用户模式。
在单用户shell 中执行命令的方式和登陆到已完成引导的系统上执行命令的方式类似。 不过在SUSE,Debian 还有Ubuntu 系统上,这时通常只安装了root分区,为了使用不在/bin,/sbin 或者 /etc 下的程序,用户必须手工安装其他文件系统。
在许多单用户环境下,文件系统的根目录是按只读方式安装的。 如果/tmp 是根文件系统的一部分,那么许多要使用临时文件的命令(如vi)都不能执行。 为了解决这个问题,必须先把根文件系统(/)以读写方式重新安装,再开展单用户模式的交互操作。 下面这条命令通常就能实现这个技巧:
正常的自动引导过程会运行fsck命令,检查并修复文件系统。 在以单用户模式启动系统时,可能需要手工执行fsck。
当单用户shell退出时,系统将尝试继续引导进入多用户模式。
2.5 执行启动脚本
到了系统准备运行其启动脚本的时候,我们就看出它是Linux系统了。 启动脚本就是普通的shell 脚本,由init根据一定的算法来选择并运行它们,尽管算法有时候有些复杂,但还是相当容易理解的。
2.6 多用户运行
在初始化脚本运行过后,系统就是完全运行的系统了,不过现在用户还不能登陆进来。 为了在某个特定终端(包括控制台)上接受用户登陆,必须有一个getty 进程监听终端或者控制台。 Init 直接生成这些getty进程,完成引导过程。 Init 还负责生成图形登陆系统,如xdm或者gdm。
即使在引导文成以后,init 还继续担当重要的角色,init拥有一个单用户和几个多用“运行级”,运行级决定启动系统的哪些资源。
三. 引导PC
PC的引导过程是一次长时间的考验,在引导一台机器的时候,它是从执行存储在ROM中的代码开始的。 根据机器类型的不同,这些代码的确切位置和特性也不相同。 在明确为UNIX 或者其他专有操作系统而设计的机器上,这些代码通常是固件。 它知道怎么使用连接到机器的设备,知道怎么和网络进行基本通信,还知道怎么理解基于磁盘的文件系统。 像这样知道一切的固件对于系统管理员来说是非常方便的。 如: 只要键入新内核的文件名,这种固件就知道怎么定位并取该文件。
在PC上, 这种初始化的引导代码通常叫作BIOS (Basic Iput/Output System)。 同专有机器的固件相比,它极为简单。 实际上,PC拥有几种级别的BIOS:一个用于机器本身,一个用于显示卡,另一个用于SCSI卡,还有一个用于其他外设(如网卡)。
内置的BIOS 知道主板上的一些设备的信息,如IDE 控制器(和磁盘),键盘,串口和并口等。 SCSI卡通常只知道与它们相连的设备。 现代的BIOS 通常允许用户在启动时按下一个或者两个特殊键来进入一种配置模式。 大多数BIOS在启动时会告诉用户有哪些特殊键。
BIOS 通过让用户选择从什么设备进行引导,BIOS一般局限与从第一个IDE CD-ROM 驱动器或第一个IDE 硬盘引导。 一旦机器确定从什么设备来启动,那么它将尝试加载磁盘开头512个字节的信息。 这512字节的段叫MBR(Master Boot Record: 主引导记录)。 MBR 包含一个程序,该程序告诉计算机从磁盘哪个分区加载第二个引导程序(引导加载程序,boot loader)。
默认的MBR 是一个简单的程序,它告诉计算机从磁盘上的第一个分区获取引导加载程序。 Linux 提供了一个更为复杂的MBR,它知道怎么去处理多操作系统和多内核。 一旦MBR 已经选定从什么分区进行引导,它就视图加载针对那个分区的引导加载程序,之后,由引导加载程序复杂加载内核。
3.1 引导加载程序:LILO 和 grub
3.1.1GRUB 全面统一的引导加载程序
GRUB(Grand Unified Boot Loader)是redhat,suse 和Fedora 系统默认的引导加载程序。 对于在同一主机上运行多个操作系统的用户,或者对于积极从事于内核开发的用户来说,Grub 用的非常多。 Grub 对于频繁改变系统配置的用户来说也非常有帮助。 每次改变LILO 的配置之后,必须重新把它安装到引导记录(MBR)里,GRUB 于此不同,它会在启动时读入自己的配置文件,省却了上述容易忘记的管理步骤。
用户通过运行grub-install 把Grub 安装到引导驱动器上。 这条命令的参数是要引导的设备名。 Grub 给物理磁盘命令的方法和Linux 的习惯标准不一样。
Grub 的命令规则如:(hd0,0).
第一个数值表示物理驱动器号(从0开始),第二个数值表示分区号(也是从0开始)。 所以这里(hd0,0)等同于Linux 设备/dev/hda1. 因此,如果用户想要在主(primary)设备上安装GRUB,应该使用命令:
#grub-install ‘(hd0,0)’
这里必须用引号来避免shell 用它自己的方式来解释括号。
在默认情况下,grub 从/boot/grub/grub.conf读取它的默认引导配置。 如:
这个例子配置了2种操作系统。 如果在GRUB在5s内(timeout=5)没有接收到任何来自键盘的输入,那么就自动引导default=0. “Red Hat Enterprise Linux AS (2.6.9-78.ELsmp)” 配置根据根文件系统是GRUB设备(hd0,0)。 GRUB从kernel /boot/vmlinuz-2.6.9-78.ELsmp加载内核,而且在加载内核的时候显示文件 (hd0,0)/boot/grub/splash.xpm.gz作为splashimage,即通常所说的启动界面。
GRUB 支持一种功能强大的命令界面,而且能随时编辑配置文件中的配置项。 在GRUB的启动画面键入C 就可以进入命令行模式。 从命令行可以启动grub.conf 文件里没有列出的操作系统,额可以显示系统信息,还可以执行对文件系统的基本测试。 用户还能够在命令行上小年感受到类似shell的功能。 如:命令补全,光标移动等。 通过grub.conf 文件能做到的事情,也能够通过grub命令行实现。
在命令行上按下<Tab>键就可以看到可能命令的快捷清单。
3.1.2 LILO: 传统的Linux 引导加载程序
LILO要用libo命令来配置和安装。 Libo 命令根据文件/etc/lilo.con的内容安装配置信息。 要改变引导配置,只要更新/etc/lilo.conf 并重新运行lilo即可。 引导过程每次发生变化时,都必须重新配置LILO。 也就是说,当用户每次想要添加一个新的引导分区以及每次有一个新的内核要引导时,都要重新配置LILO.
因为用的是Redhat 系统,没有这个文件,感兴趣的,可以自己看下这个配置文件。
3.2 内核选项
LILO 和GRUB 都能把命令行选项传送给内核。 这些选项往往用来修改内核参数的取值,命令内核探测特殊的设备,指定init 所在的路劲,或者指派一个特定的根设备。 内核启动时的选项参考下表:
3.3PC上的多重引导
由于PC上可以运行多种操作系统,因此配置一台机器使它能够引导几种不同的系统就成为相当常见的做法。 要实现这一点,需要配置一个引导加载程序能够认出磁盘上所有不同操作系统。
每个磁盘分区都可以拥有自己的第二个阶段的引导加载程序。 但是,整个磁盘却只有一个MBR。 在建立多重引导配置时,必须决定哪一个引导加载程序将陈给主引导加载程序。 对于有一个Linux 分区的系统来说,LILO 和GRUB 通常是最佳选择,在多重引导的情况下,GRUB 要比LILO好。
3.4 GRUB 的多重引导配置
多重引导的GRUB 系统和单一引导的GRUB系统很相像。 先装好所有想要的操作系统,然后在对/boot/grub/grub.conf 做相应的修改
引导Windows 的grub.conf 配置看上去和引导Unix 或者Linux系统的配置不一样:
Chainloader 这个选项从一个指定的位置加载引导加载程序(本例中是主IDE驱动器上第一个分区的第一个扇区)。 Rootnoverify选项确保GRUB不会尝试安装指定的分区。 这个选项避免了GRUB被它不能理解的分区搞糊涂,比如NTFS 分区或者GRUB所能图区的范围之外的其他分区。
下例中的grub.conf 文件能够从分区1引导Window XP,从分区2引导Redhat,从分区3引导Fefora:
关于LILO 的多重引导配置,这里就不多说了。 感兴趣的自己研究。
四.引导单用户模式
单用户模式是一种在不影响其他用户(或者不被其他用户影响)的情况下,修改系统配置或者实施维护工作的好方式。 单用户模式也是在受损系统上展开恢复工作所采用的模式。
向引导加载程序传递参数是进入单用户模式最常用的做法。 不过用户也可以在其他运行级别内通过执行telinit 1 命令进入单用户模式。 除非正式调用和引导有关的问题,否则没必要重新启动系统。
文件系统的根目录在系统引导时以只读方式安装,这是一种预防系统不稳定的手段。 如果需要通过修改位于根文件系统中的一个配置文件或者命令来解决问题,或者需要执行一条会修改这些文件的命令,那么上述手段就会妨碍我们达到预期的目的。 为了解决这个问题,可以用下面的命令重新按读写模式安装根文件系统:
#mount –o remount –w /
4.1 用GRUB 引导单用户模式
在Grub下,不需要使用命令行就能进入单用户模式。 GRUB 的作者认识到,引导选项应该很容易就能修改,并且用 a 键作为相应的工具来设置引导选项。 在grub的启动界面中,加亮显示所需的内核,按下 a 键后添加引导选项即可。 要引导单用户模式,就在现有的内核选项之后再加上single 标志。 如:
Grub append> ro root=LABLE=/ rhgb quiet single
4.2 用LILO 引导单用户模式
各个发行版本提供了不同的访问LILO 命令行的途经。 如果在偏爱GRUB的redhat,fefora 或者suse 上安装了LILO,那么就要从绚丽的全彩色启动界面上选择 command line这个菜单选项。 Debin 和ubuntu用户则应该在bios 刚执行完内存检查和其他系统自检后马上按下shift 键不松手。
在LILO 提示符处,键入想要的配置的标签名,后跟-s 或者single。 如,debian 自带的默认配置叫作“linux”,所以要引导该配置进入单用户模式。 应该使用:
LILO:linux single
五. 启动脚本
从单用户模式退出以后(或者在自动引导过程中要运行单用户shell的时刻),init 执行系统的启动脚本,这些脚本实际上只是由sh(实际是bash)解释的普通shell 脚本。 在不同的系统中,这些脚本的确切位置,内容和组织结构有相当大的区别。
经常在启动脚本中执行的一些任务如下:
(1)设置计算机的名称
(2)设置时区
(3)采用fsck检查磁盘(只在自动模式下)
(4)安装系统的磁盘
(5)从/tmp 目录删除旧文件
(6)配置网络接口
(7)启动守护进程和网络服务
大多数启动脚本的内容相当详尽,而且能打印出正在做的每件事情的描述。 如果系统在引导过程中出现问题而挂起,或者用户正在视图确定错误在某个脚本中的位置时,这种打印信息的做法就会起到很大的帮助。
在以前的系统上,系统管理员常做的一件事就是修改启动脚本,使得脚本为特定的环境做合适的事情。 不过,由于软件打包的粒度更细,而且会频繁从Internet 进行更新,迫使系统采用了一种更可靠的方式。 现在,系统装了各个软件安装的大量启动小脚本,这些脚本从若干独立的文件读取它们的本地配置信息。 这些本地配置文件通常采用微小sh脚本的形式来设置shell 变量的值,然后启动脚本再用这些变量的取值。