6.2  Linux系统的引导过程
Linux系统的引导和初始化过程可以分为两个阶段,如图6.3所示
6.3  Linux内核启动过程示意图
1阶段:完成硬件检测、初始化和内核的引导。
2阶段:主要是init初始化进程的执行。
1.BIOS自检
计算机通电后,首先由BIOS进行自检,即所谓的POST(Power On Self Test),对硬件进行
检测,然后BIOS 必须确定要使用哪个设备来引导系统,此时会根据CMOS中设置的引导顺序,搜索处于活动状态并可引导的设备(硬盘、CDROM、USB设备或软盘),当到一个引导设备之后,从中读出引导块或MBR(MBR,Master Boot Record)。主引导记录MBR中包含主引导加载程序。MBR是一个512B大小的扇区,位于磁盘的第一个扇区中(0道0面1扇区)。当MBR被加载到RAM中之后,BIOS会把控制权交给MBR。
注意,要看MBR的内容,可以执行如下命令:
# dd if=/dev/hda of=mbr.bin bs=512 count=1        ///dev/hda上读取前512B的内容,将其写入mbr.bin文件中
# od -xa mbr.bin                        //以十六进制和ASCII码格式打印这个二进制文件的内容
MBR中的主引导加载程序是一个512B大小的映像,其中包含程序代码和一个分区表。前446B是主引导加载程序,其中包含可执行代码和错误消息文本。接下来的64B是分区表,其中包含4个分区的记录(每个记录的大小是16个字节)。MBR以两个特殊数字的字节(0xAA55)结束。这个数字会用来进行MBR的有效性检查。
2.启动GRUB
GRUB是引导加载程序,会引导操作系统。当机器引导它的操作系统时,BIOS会读取引导介质上最前面的512字节(MBR,Master Boot Record)
主引导加载程序(第一阶段的引导加载程序)的主要作用是查并加载次引导加载程序,它是通过在分区表中查一个活动分区来实现这种功能的。当到一个活动分区时,会扫描分区表中的其它分区,以确保它们都不是活动的。当这个过程验证完成之后,就将活动分区的引导记录(第二阶段的引导加载程序)从这个设备中读到RAM中,并执行它。
第二阶段的引导加载程序(次引导加载程序)可以更形象地称为内核加载程序。主要作用是将默认的内核映像和initrd映像加载到内存中。
在PC环境中,第一阶段和第二阶段的引导加载程序一起称为GRand Unified Bootloader(GRUB)。在GRUB命令行环境中(启动电脑后,在GRUB界面中按C键进入),可以使用initrd映像引导一个特定的内核,方法如下:
grub> kernel (hd0,2)/
Possible files are: lost+found sys proc var tmp dev etc root selinux usr bin boot home li
b media mnt opt sbin srv misc tftpboot .autofsck net cache_db
grub> kernel (hd0,2)/boot/vmlinuz-2.6.18-128.el5
  [Linux-bzImage, setup=0x1e00, size=0x1bbeb4]
grub> initrd (hd0,2)/boot/initrd-2.6.18-128.el5.img
  [Linux-initrd @ 0x2fd79000, 0x266c72 bytes]
grub>
当内核映像被加载到内存后,内核阶段就加开始了。
3.加载内核
当内核映像被加载到内存中,并且阶段2的引导加载程序释放控制权之后,内核阶段就开始了。内核映像并不是一个可执行的内核,而是一个压缩过的内核映像。通常它是一个 zImage(压缩映像,小于512KB)或一个bzImage(较大的压缩映像,大于512KB)。在这个内核映像前面是一个例程,它实现少量硬件设置,并对内核映像中包含的内核进行解压,然后将其放入高端内存中,如果有初始RAM磁盘映像,就会将它移动到内存中,并标明以后使用。然后该例程会调用内核,并开始启动内核引导的过程。
关机程序代码在内核引导过程中,初始RAM磁盘(initrd)是由次引导加载程序加载到内存中的,它会被复制到RAM中并挂载到系统上。这个initrd会作为RAM中的临时根文件系统使用,并允许内核在没有挂载任何物理磁盘的情况下完整地实现引导。由于与外围设备进行交互所需要的模块可能是initrd的一部分,因此内核可以非常小,但是仍然需要支持大量可能的硬件配置。在内核引导之后,就可以正式挂载根文件系统了,此时会将initrd根文件系统卸载掉,挂载真正的根文件系统。
注意:在一个没有硬盘的嵌入式环境中,initrd可以是最终的根文件系统,或者通过网络文件系统(NFS)挂载最终的根文件系统。
4.执行init进程
内核被载入内存,开始运行并初始化所有的设备驱动程序和数据结构等之后,内核将生成第一个进程―init(实际上依次寻/sbin/init/etc/init/bin/init/bin/sh,将执行第一个到的,如果这4个文件都不存在,将给出“No init found. Try passing init= option to kernel."错误提示,内核启动失败。详细分析见5.3节)。init进程是一个由内核启动的用户级进程,是系统上运行的所有其它进程的父进程,它会观察其子进程,并在需要的时候启动、停止、重启它们,主要用来完成系统的各项配置。该进程对于Linux系统的正常工作是非常重要的。
init的主要工作是根据/etc/inittab文件来执行相应的脚本,进行系统的初始化,如设置键盘、字体、装载模块、设置网络等。所以,init进程执行的每一步都是由/etc/initab文件中的配置决定的以下是RadHat/etc/inittab文件的例子:
# inittab      This file describes how the INIT process should set up
#              the system in a certain run-level.
# Author:      Miquel van Smoorenburg, <miquels@drinkel.>
#              Modified for RHS Linux by Marc Ewing and Donnie Barnes
# Default runlevel. The runlevels used by RHS are:
#  0 - halt (Do NOT set initdefault to this)    //停机(不要把initdefault设置为0,否则开机之后就会自动关机
#  1 - Single user mode        //单用户模式
#  2 - Multiuser, without NFS (The same as 3, if you do not have networking)        //多用户模式,但是没有NFS
#  3 - Full multiuser mode        //完全多用户模式
#  4 - unused                //没有使用
#  5 - X11                //X-windows模式
#  6 - reboot (Do NOT set initdefault to this)    //系统重新启动(不要把initdefault设置为6,否则开机之后就会重启
#
id:5:initdefault:            //该命令指出缺省的运行级别为5,即开机后进入X-window模式
# System initialization.
#系统启动之后自动执行/etc/rc.d/rc.sysinit脚本,当运行级别为5时,会以5为参数运行/etc/rc.d/rc 5脚本,
# init进程将等待其返回(wait
si::sysinit:/etc/rc.d/rc.sysinit
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
# Trap CTRL-ALT-DELETE
#在启动过程中如果按Crtl-Alt-Delete,将执行/sbin/shutdown -t3 -r now命令重启系统
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# When our UPS tells us power has failed, assume we have a few minutes
# of power left.  Schedule a shutdown for 2 minutes from now.
# This does, of course, assume you have powerd installed and your
# UPS connected and working correctly.
#如果系统有UPS电源,该行命令设定系统在掉电时提示“电源关闭,系统正在关闭”,并且在2min后自动关机
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
# If power was restored before the shutdown kicked in, cancel it.
#如果工作电源恢复,该行命令提示“电源恢复,取消关机”,并且取消关机
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
# Run gettys in standard runlevels
# init进程打开6个终端(虚拟控制台),以ttyn为参数执行/sbin/mingetty程序,打开ttyn终端用于用户登录
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
>#  0:12345:respawn:/sbin/mingetty tty0
># 在15各个级别上以tty0为参数执行/sbin/mingetty程序,打开tty0终端用于用户登录,
># 如果进程退出则再次运行mingetty程序
# Run xdm in runlevel 5
#在级别5上运行xdm程序,提供xdm图形方式登录界面,并在退出时重新执行(respawn
x:5:respawn:/etc/X11/prefdm -nodaemon
/etc/inittab文件是以行为单位的描述性(非执行性)文本,每个指令行都具有以下格式:
Idrunlevelsactionprocess
从代码中可以看到,etc/inittab中语句的每一行包含4个域,格式如下。
(1)id:是指入口标识符,它是一个字符串,是由两个独特的字元所组成的标识符,这个标识符在此文件中是唯一的。文件中的某些记录必须使用特定的id才能使系统工作正常。对于getty或mingetty等其它login程序项,要求id与tty的编号相同,否则getty程序不能正常工作。
(2)runlevels:runlevels域给出的是本行的运行级别。运行级别会指出下一个操作域中的action以及process域会在哪些runlevels中被执行。而在正常的启动程序之后,root用户可以使用telinit这个指令来改变系统的runlevels。假定在Linux系统中runlevels的预设值是5,那么只有那些每一列中runlevel域的值为5时,后面的process才会被执行。所以,如果系统的runlevels值不同的话,所执行的process也不一样,所以系统启动时的资源配置情况,在不同的runlevels下会有差异。runlevels一般使用0~6以及S或s。0为shutdown;1为重启至单用户模式;2为无NFS支持的多用户模式;3是完全多用户模式(也是最常用的级别);4保
留给用户自定义;5表示XDM图形登录方式;6为重启;S和s意义相同,表示单用户模式,且无需inittab文件,因此也不在inittab中出现,实际上,进入单用户模式时,init直接在控制台(/dev/console)上运行/sbin/sulogin。在一般的系统实现中,0、1、6运行级别被系统保留,使用2、3、4、5几个级别,7~9级别也是可以使用的,传统的Unix系统没有定义这几个级别。runlevels可以是并列的多个值,以匹配多个运行级别,对大多数action来说,仅当runlevels与当前的运行级别匹配才会执行。
注意:运行级别1是单用户模式,所谓单用户指的是系统运行在唯一用户(超级用户)模式下。而多数情况下,系统运行在多用户模式下。在启动出错、文件系统出错等情况下,进入单用户模式,可以进行修复操作。
(3)action:是指动作,指出init程序执行相应process的方式,取值及其含义见表6.5。
表6.5 action取值及其含义
动作
说明
initdefault
指定缺省的运行级别(runlevelinitdefault是一个特殊的action值,用于标识缺省的启动级别;当init由核心激活 以后,它将读取inittab中的initdefault项,取得其中的runlevel,并作为当前的运行级 别。如果没有inittab文件,或者其中没有initdefault项,init将在控制台上请求输入 runlevel
sysinit
指定运行的第一个程序/脚本,此时runlevels域不起作用
boot
sysinit之后执行,runlevels域不起作用
bootwait
boot,但init会等待该命令结束
once
在进入有runlevels指定的运行级别时运行
wait
同上,但init会等待该命令结束
respawn
在进入相应runlevel时执行,并且若该进程结束,init会再起一个进程执行同样的命令
ctrlaltdel
指定在用户按下Ctrl-Alt-Del时执行的命令
注意action为sysinit、boot、bootwait所对应的process将在系统启动时无条件运行,会忽略其中的runlevel,其余的action(不含 initdefault)都与某个runlevel相关。
(4)process:是指要执行的程序,程序后面可以带参数。
5.执行/etc/rc.d/rc.sysinit
/etc/rc.d/rc.sysinitinit进程执行的第一个Shell脚本文件,是每一个运行级别都要首先运行的重要脚本。/etc/rc.d/rc.sysinit主要做在各个运行级别中相同的初始化工作,如下:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。