转-Linux启动过程详解(inittab、rc.sysinit、rcX.d、rc.local)

http://blog.chinaunix.net/space.php?uid=10167808&do=blog&id=26042
 
1)BIOS自检
2)启动Grub/Lilo
3)加载内核
4)执行init进程
5)经过/etc/inittab文件进行初始化
6)登录Linux

1)BIOS自检
   a)POST(Power On Self Test),对硬件进行检测
   计算机在通电后首先由BIOS进行自检,即所谓的POST(Power On Self Test),对硬件进行检测
   依据BIOS内设置的引导顺序从硬盘、软盘或CDROM中读入"引导块"
   在PC中,Linux是从BIOS中的地址0xFFFF0处开始的
   BIOS的第一个步骤是加电自检(POST),对硬件进行检测
       第二个步骤是进行本地设备的枚举和初始化
   BIOS由两部分组成: POST代码和运行时服务
   当POST完成后,它从内存中清理出来,但BIOS运行时服务依然保留在内存中,目标操做系统可使用这些服务
   要引导一个操做系统,BIOS运行时会按照CMOS的设置的顺序来搜索处于活动状态并可引导的设备:软盘、CD-ROM、硬盘上的分区、网络上的某个设备、USB(一般Linux是从硬盘引导的
   主引导记录MBR中包含主引导加载程序。MBR是一个512字节大小的扇区,位于磁盘上的第一个扇区中(0道0柱面1扇区))当MBR被加载到RAM中以后,BIOS会把控制权交给MBR

   b)提取MBR的信息
   要看MBR的内容,请使用下面的命令
   #从/dev/sda上读取前512个字节的内容,并将其写入mbr.bin文件中
   [root@localhost pam.d]# dd if=/dev/sda of=mbr.bin bs=512 count=1

   #以十六进制和ASCII码格式打印这个二进制文件的内容
   [root@localhost pam.d]# od -xa mbr.bin
0000000 48eb 0090 d08e 00bc fb7c d88e b9fc 0080
      k H dle nul   so P 2)启动GRUB/Lilo
   GRUB和LILO都是引导加载程序,它们会引导操做系统。当机器引导它的操做系统时,BIOS会读取引导介质上最前面的512字节(即MBR: master boot record)

3)加载内核
   当内核映像被加载到内存后,内核阶段就加开始了
   内核映像并非一个可执行的内核,而是一个压缩过的内核映像。一般它是一个zImage(压缩映像,小于512KB)或bzImage(较大的压缩映像,大于512KB),它是提早使用zlib进行压缩的
   在这个内核映像前面是一个例程,它实现少许硬件设置,并对内核映像中包含的内核进行解压,而后将其放入高端内存中,若是有初始RAM磁盘映像,就会将它移动到内存中,并标明之后使用,而后此例程会调用内核,并开始启动内核引导的过程
   在GRUB命令中,咱们可使用initrd映像引导一个特定的内核,方法以下:
   grub> kernel /bzImage-2.6.14.2
   [Linux-bzImage, setup=0x1400, size=0x29672e]

   grub>initrd /initrd-2.6.14.2.img
   [Linux-initrd @ 0x5f13000, 0xcc199 bytes]

   grub> boot
   Uncompressing Linux... Ok, booting the kernel.

   若是不知道要引导的内核的名称,只需使用/而后按下Tab键,就会显示内核和initrd映像列表

   对grub命令行进行加密
   a)使用命令/sbin/grub-md5-crypt来产生grub使用的密码
   [root@localhost pam.d]# /sbin/grub-md5-crypt
Password:
Retype password:
$1$3YbPF$zFVRY6J8VxNR9Ok4fXRkr1
   b)修改/etc/grub.conf加入password --md5 $1$3YbPF$zFVRY6J8VxNR9Ok4fXRkr1 必定要放在title以前
   这样重启系统时在grub的启动grub菜单时,想再按e命令进行编辑时,必须先按p键后输入密码才成

4)执行init进程
   init进程是全部进程的起点,内核在完成内核引导后,即在本线程(进程)空间内加载init程序,它的进程号为1
   init进程是全部进程的发起者和控制者
   init进程有两个做用:
扮演终结父进程的角色:全部的孤儿进程都会被init进程接管
进入某个特定的运行级别时运行相应的程序,以此对各类运行级别进行管理,这个做用由/etc/inittab文件定义的

5)经过/etc/inittab文件进行初始化
   init进程的工做是根据/etc/inittab来执行相应的脚本进行系统初始化,如设置键盘、字体,装载模块,设置网络等,对于RedHat来讲,按如下顺序执行
   a)执行/etc/rc.d/rc.sysinit(由init执行的第一个脚本)
此步可进行的工做有:
设置$PATH变量
配置网络
为虚拟内存启动交换
设置系统的主机名
检查root文件系统,以进行必要的修复
检查root文件系统的配额
为root文件系统打开用户和组的配额
以读/写的方式从新装载root文件系统
清除被装载的文件系统表/etc/matb
把root文件系统输入到mtab
使用系统为装入模块作准备
查找模块的相关文件
检查文件系统,以进行必要的修复
加载全部其余文件系统
清除几个/etc文件,如/etc/mtab、/etc/fastboot和/etc/nologin
删除UUCP的lock文件
删除过期的子系统文件
删除过期的pid文件
设置系统时钟
打开交换
初始化串行端口
装入模块

b)执行/etc/rc.d/rcX.d[KS]
首先终止K开头的服务(用来关闭一个服务),而后启动S开头的服务(用来启动一个服务)
对每个运行级别来讲,在/etc/rc.d子目录中都有一个对应的下级目录。
这些运行级别的下级子目录的命名方法上rcX.d, 其中X就是表明运行级别的数字
在各个运行级别的子目录中,都创建有到/etc/rc.d/init.d子目录中命令脚本程序的符号连接
连接的名称在K与S后有一个数字,表示执行顺序,数字小的先执行如K01tog-pegasus   、 S00microcode_ctl
对以K开头的脚本执行时系统会传递stop参数,而S开头的脚本系统会传递start参数

c)执行/etc/rc.d/rc.local
Redhat中运行模式2,3,5都把/etc/rc.d/rc.local做为初始化脚本中的最后一个文件,因此用户能够本身在这个文件中添加一些须要在其余初始化工做以后,登录以前执行的命令


6)执行/bin/login
login程序会提示使用者需输入账号与密码,接着编码并确认密码的正确性,若两者相合,则为使用者进行初始化环境,并将控制权交给shell,即等用户登陆。
  
----------------至此,Linux启动过程所有结束----------------------
Linux init详解
“Uuno on numero yksi ”(Slogan for a series of Finnish movies.)
本章描述 init进程,它是内核启动的第一个用户级进程。 init有许多很重要的任务,好比象启动 getty(用于用户登陆)、实现运行级别、以及处理孤立进程。本章解释了怎样配置 init以及如何运用不一样的运行级别。
 
第一步
init
对于Linux系统的运行来讲, init程序是最基本的程序之一。但你仍能够大部分的忽律它。一个好的Linux发行版本一般随带有一个 init的配置,这个配置适合于绝大多数系统的工做,在这样一些系统上不须要对 init作任何事。一般,只有你在碰到诸如串行终端挂住了、拨入(不是拨出)调制解调器、或者你但愿改变缺省的运行级别时你才须要关心 init
当内核启动了本身以后(已被装入内存、已经开始运行、已经初始化了全部的设备驱动程序和数据结构等等),经过启动用户级程序 init来完成引导进程的内核部分。所以, init老是第一个进程(它的进程号老是1)。
内核在几个位置上来查寻 init,这几个位置之前经常使用来放置 init,可是 init的最适当的位置(在Linux系统上)是/sbin/init。若是内核没有找到 init,它就会试着运行/bin/sh,若是仍是失败了,那么系统的启动就宣告失败了。
init开始运行,它经过执行一些管理任务来结束引导进程,例如检查文件系统、清理/tmp、启动各类服务以及为每一个终端和虚拟控制台启动 getty,在这些地方用户将登陆系统(见第八章)。
在系统彻底起来以后, init为每一个用户已退出的终端重启 getty(这样下一个用户就能够登陆)。 init一样也收集孤立的进程:当一个进程启动了一个子进程而且在子进程以前终止了,这个子进程马上成为 init的子进程。对于各类技术方面的缘由来讲这是很重要的,知道这些也是有好处的,由于这便于理解进程列表和进程树图。[1]  init的变种不多。绝大多数Linux发行版本使用 sysinit(由Miguel van Smoorenburg著),它是基于System V的 init设计。UNIX的BSD版本有一个不一样的 init。最主要的不一样在于运行级别:System V有而BSD没有(至少是传统上说)。这种区别并非主要的。在此咱们仅讨论 sysvinit
 
配置init以启动getty:/etc/inittab文件

init启动后, init读取/etc/inittab配置文件。当系统正在运行时,若是发出HUP信号, init会重读它;[2] 这个特性就使得对 init的配置文件做过的更改不须要再从新启动系统就能起做用了。
/etc/inittab文件有点复杂。咱们将从配置 getty行的简单状况提及。etc/inittab中的行由四个冒号限定的域组成:
id:runlevels:action:process
下面对各个域进行了描述。另外,/etc/inittab能够包含空行以及以数字符号(’#’)开始的行;这些行均被忽略。

id

这肯定文件中的一行。对于 getty行来讲,指定了它在其上运行的终端(设备文件名/dev/tty后面的字符)。对于别的行来讲,是没有意义的(除了有长度的限制),但它必须是惟一的。

runlevels

该行应考虑的运行级别。运行级别以单个数字给出,没有分隔符。(运行级别在下一节中讨论。)

action

对于该行应采起的动做,也即,respawn再次运行下一个域中的命令,当它存在时,或者仅运行一次。

process

要运行的命令。
为了在第一个虚拟终端上(/dev/tty1)运行 getty、在全部的正规多用户运行级别中(2-5),应该写入下面这行:
1:2345:respawn:/sbin/getty 9600 tty1
第一个域指出这是对应于/dev/tty1的行。第二个域说明它应用于运行级别2,3,4和5。第三个域是说在命令退出以后,应被再次执行(所以,用户能够登陆、退出而且再次登陆)。最后一个域是在第一个虚拟终端上运行 getty的命令。[3] 
若是你须要给系统增长终端或者拨入调制解调器线路,你应该给/etc/inittab增长更多的行,每一行对应一个终端或一条拨入线。详细信息,参见 init、inittab以及 getty的manual page。
若是一个命令运行时失败了,而且init配置成重运行它,它会使用许多的系统资源:init运行它、它失败了、init再运行它、再次失败等等,没完没了。为了不这样,init将追踪一个命令重运行了多少次,而且若是重运行的频率过高,它将被延时五分钟后再运行。
一个运行级别( run level)是init以及整个系统的状态,它定义了可以提供什么系统服务。运行级别用数字来定义,见表7-1。对于如何使用用户定义运行级别(2到5)没有一致的意见。有些系统管理员使用运行级别来定义哪一个子系统工做,也即,X是否能运行、网络是否能工做等等。其余人老是让全部子系统工做着或者单独地运行以及中止它们,而不改变它们的运行级别,由于运行级别对于控制他们的系统来讲显得太粗率了。你必须本身决定,可是按照你的Linux发行版本的作法来作也许是最容易的了。
表7-1. 运行级别数
0
终止系统
1
单用户模式(用于特别管理)
2-5
正常操做(用户定义)
6
重启动
运行级别经过以下行所示的行在/etc/inittab中配置:
l2:2:wait:/etc/init.d/rc 2
第一个域是任意给的符号,第二个域指出是运行级别2。第三个域说明当进入该运行级别时, init应该运行第四个域中的命令一次,而且 init应该等待它的结束。在进入运行级别2时,在须要时/etc/init.d/rc命令运行或者中止服务。
第四个域中的命令作全部设置一个运行级别的艰巨工做。它启动尚未运行的服务,而且中止在新的运行级别中不该再运行的服务。确切的命令是什么以及运行级别是如何配置的,依赖于各个Linux发行版本。
init开始运行时,它在/etc/inittab中查寻一行,该行指定了缺省的运行级别:
id:2:initdefault:
经过给内核一个single或emergency命令行参数,你能够在 init运行开始时转到一个非缺省的运行级别上。例如,内核命令行参数能够经过LILO给出。这使得你能够选择单用户模式(运行级别 1)。
当系统正在运行时, telinit命令能够改变运行级别。当运行级别改变时,init就运行/etc/inittab中相应的命令。
 
/etc/inittab中的特殊配置

/etc/inittab有些特殊的特性,它容许 init对特别的环境做出响应。这些不同凡响的特性在第三个域中由关键字标出。一些例子以下:

powerwait

当系统电源失败时,容许 init关闭系统。这里假设使用了UPS以及用于监视UPS和通知init电源失败的软件。

ctrlaltdel

当用户在控制台上按了ctrl-alt-del组合键时,容许 init从新(启动)引导系统。注意,系统管理员可以配置对ctrl-alt-del组合键的响应为其它的什么,例如,忽略它,若是系统是在一个公共的环境中(或者开始 nethack。)

sysinit

当系统引导时要执行的命令。例如,这个命令一般是清理/tmp。
上面所列并非所有。对于全部的关键字以及如何使用它们请参见inittab的manual page。
 
启动(引导)进入单用户模式

一个很重要的运行级别是单用户模式( single user mode)(运行级别1),在这个模式中只有系统管理员在使用机器而且只有不多的系统服务在运行,如登陆服务。对于一些管理任务来讲单用户模式是必须的, [4] 如在/usr分区上运行 fsck,由于这须要该分区没被加载,除非几乎全部的系统服务都被终止了,不然不可能会有这种状况。
经过 telinit请求运行级别1,一个运行着的系统能够转换到单用户模式。在启动时,能够经过在内核的命令行上给出single或emergency来进入单用户模式:内核一样也将命令行给 initinit会理解那个单词而且不会使用缺省的运行级别。(内核命令行输入的方法依赖于系统是如何引导的。)
在加载文件系统以前,引导进入单用户模式有时是须要的,这样就能够手工运行 fsck命令了,不然的话极可能损坏/usr分区(在一个有问题的文件系统上的任何操做会更进一步地损坏它,因此 fsck要尽早地运行)。
若是启动时fsck的自动检查失败了,启动描述文件 init就会自动地进入单用户模式。这是试图避免系统使用一个文件系统,这个文件系统损坏的太严重以致于fsck都不可以自动地修复它。这样的毁坏状况是至关少的,一般是硬盘有问题或是在试验一个内核版本,可是有准备总比没有好。 做为一个安全措施,一个正确配置的系统应该在运行单用户模式的shell以前要求口令。不然的话,只要给LILO输入适当的一行参数就很容易地以root 身份进入系统。(固然,若是因为文件系统的问题而使/etc/passwd毁坏时,就不是这样了。若是是这样的话,你手头最好有张引导软盘。)