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 内核进程
线程
作用
Kjournald
向磁盘提交ext3 日志更新信息,每个已经安装的ext3文件系统都对应一个该进程。
Kswapd
物理内存不足时执行交换操作的进程
Kreclaimd
回收近期未用的内存页
Ksoftirqd
处理多层软中断
Khubd
配置USB 设备
在所有这些进程中,只有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)都不能执行。 为了解决这个问题,必须先把根文件系统(/)以读写方式重新安装,再开展单用户模式的交互操作。 下面这条命令通常就能实现这个技巧:
#mount –o rw,remount /
正常的自动引导过程会运行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卡,还有一个用于其他外设(如网卡)。