在启动的过程中,多次用到了Shell的脚本文件——Shell Scipt,如“$HOME/profile”、“/etc/inittab”等等。这里有必要把它们的格式和作用稍加说明。
我们把启动所需要的脚本文件分为两部分,一部分是Linux系统启动所必需的,也就是从/etc/inittab开始直到出现“Login:”提示符时要用到的所用脚本,另外一部分是用户登录后自己设定的用于支持个性化的操作环境的脚本。在后者中,我们可以设定提示符用“$”或是其它什么任意你喜欢的字符,可以设所用的Shell是bash,ksh,还是zsh。显然,这部分不是我们的重点,我们要重点描述的是前一部分——系统启动所必需的脚本。
系统启动所必需的脚本存放在系统默认的配置文件目录/etc下。用一条ls指令你可以看到所用的配置文件。不过,/etc下面还有一些子目录,比如说,rc.d就是启动中非常重要的一部分。我们主要介绍的是/etc/inittab和rc.d下的一些文件,我们还是按启动时init进程调用它们的顺序来一一介绍。
首先调用的是/etc/inittab。init进程将会读取它并依据其中所记载的内容进入不同的启动级别,从而启动不同的进程。所谓运行级别就是系统中定义了许多不同的级别,根据这些级别,系统在启动时给用户分配资源。比如说,以系统管理员级别登录的用户,就拥有使用几乎所有系统资源的权力,而一般用户显然不会被赋予如此大的特权。
下面是系统的七个启动级别。
0 系统停止。如果在启动时选择该级别,系统每次运行到inittab就会自动停止,无法启动。
1 单用户模式。该模式只允许一个用户从本地计算机上登录,该模式主要用于系统管理员检查和修复系统错误。
2 多用户模式。与3级别的区别在于用于网络的时候,该模式不支持NFS(网络文件系统)。
3 完全多用户模式。可以支持Linux的所有功能,是Linux安装的默认选项。
4 未使用的模式。
5 启动后自动进入X-windwos。
6 重新启动模式。如果在启动时选择该级别,系统每次运行到inittab就会自动重新启动,无法进入 系统。
以上这七种模式并非在启动后一成不变,如果用户是系统管理员,那么,他就可以使用“init X”(X取1,2…6中的一个)来改变运行状态。另外,如果你重新启动时,你也可以看到显示器上提示你,当前运行状态已经变为6。
让我们看一个inittab文件的实例。
id:3:initdefault: 系统默认模式为3。
#System initialization.
si::sysinit:/etc/rc.d/rc.sysinit 无论从哪个级别启动,都执行/etc/rc.d/rd.sysinit。
10:0:wait:/etc/rc.d/rc.0 从0级别启动,将运行rc.0。
11:1:wait:/etc/rc.d/rc.1 从1级别启动,将运行rc.1。
12:2:wait:/etc/rc.d/rc.2 从2级别启动,将运行rc.2。
13:3:wait:/etc/rc.d/rc.3 从3级别启动,将运行rc.3。
14:4:wait:/etc/rc.d/rc.4 从4级别启动,将运行rc.4。
15:5:wait:/etc/rc.d/rc.5 从5级别启动,将运行rc.5。
16:6:wait:/etc/rc.d/rc.6 从6级别启动,将运行rc.6。
#Things to run in every runlevel 任何级别都执行的配置文件。
ud::once:/sbin/update
#Run gettys in standard runlevels 对虚拟终端的初始化。
1:12345:respqwn:/sbin/mingetty tty1 tty1运行于1,2,3,4,5五个级别。
2:2345:respqwn:/sbin/mingetty tty2 tty2运行于2,3,4,5四个级别。
3:2345:respqwn:/sbin/mingetty tty3 tty3运行于2,3,4,5四个级别。
4:2345:respqwn:/sbin/mingetty tty4 tty4运行于2,3,4,5四个级别。
5:2345:respqwn:/sbin/mingetty tty5 tty5运行于2,3,4,5四个级别。
6:2345:respqwn:/sbin/mingetty tty6 tty6运行于2,3,4,5四个级别。
#Run xdm in runlevel 5 在级别5启动X-Window。
x:5:respawn:/usr/bin/X11/xdm -nodaemon
现在详细解释一些inittab的内容。
从上面的文件我们可以看出,inittab的每一行分成四个部分,这四个部分的格式如下:
id:runleveld:action:process
它们代表的意义分别如下:
id:代表有几个字符所组成的标识符。在inittab中任意两行的标识符不能相同。
runlevels:指出本行中第三部分的action以及第四部分的进程会在哪些runlevel中被执行,这一栏的合法值有0,1,2...6,s以及S。
action:这个部分记录init进程在启动过程中调用进程时,对进程所采取的应答方式,合法的应答方式有下面几项:
initdefault:指出系统在启动时预设的运行级别。上例中的第一行就用了这个方式。所以系统将在启动时,进入 runlevel为3的模式。当然,可以把3改为5,那将会执行/etc/rc.d/rc.5,也就是X-Window。
sysinit: 在系统启动时,这个进程肯定会被执行。而所有的inittab的行中,如果它的action中有boot及bootwait,则该行必须等到这些action为sysinit的进程执行完之后才能够执行。
wait:在启动一个进程之后,若要再启动另一个进程,则必须等到这个进程结束之后才能继续。
respawn:代表这个process即使在结束之后,也可能会重新被启动,最典型的例子就是getty。
明白了inittab的意思,让我们回过头来看看启动过程。
首先,执行的是/etc/rd.c/rc.sysinit。这里不再给出它的程序清单,只给出它的主要功能:
1) 检查文件系统
包括启用系统交换分区,检查根文件系统的情况,使用磁盘定额程序quato(可选项),安装内核映象文件系统proc,安装其它文件系统。
2 )设置硬件设备
设定主机名,检查并设置PNP设备,初始化串行接口,初始化其它设备(根据你的机器配置情况决定)。
3)检查并载入模块
执行完rc.sysinit并返回inittab后,init进程会根据inittab所设定的运行级别去执行/etc/rc.d目录下的相应的rc文件。比如说运行级别为3,相应的rc文件即为rc.3。这些文件将运行不同的启动程序去初始化各个运行级别下的系统环境,这部分启动程序最重要的作用之一是启动系统的守护进程,如在rc.3中,就要启动cron,sendmial等守护进程。
做完这一步,init进程将执行getty进程从而等待用户的登录,也就是说,Linux的启动全过程已经结束了,剩下的部分,就是整个系统等待用户需求,并为用户提供服务了。
Linux的初始化到此就结束了,回过头来看看,它确实跟我们在开始时假设的那个简单的操作系统的初始化有许多相似之处,这些是所有初始化都应该有的相似点,希望您在分析完Linux源代码后,能编制出自己的操作系统的初始化代码。