Linux从开机到登录启动过程综述(3)

对于I386平台

  基本相同。

  对于2.4.x版内核

  这一部分的启动过程在2.4.x内核中简化了不少,缺省的独立初始化过程只剩下网络(sock_init())和创建事件管理核心线程,而其他所需要的初始化都使用__initcall()宏包含在do_initcalls()函数中启动执行。

  init进程和inittab引导指令

  init进程是系统所有进程的起点,内核在完成核内引导以后,即在本线程(进程)空间内加载init程序,它的进程号是1。

  init程序需要读取/etc/inittab文件作为其行为指针,inittab是以行为单位的描述性(非执行性)文本,每一个指令行都具有以下格式:

  id:runlevel:action:process其中id为入口标识符,runlevel为运行级别,action为动作代号,process为具体的执行程序。

  id一般要求4个字符以内,对于getty或其他login程序项,要求id与tty的编号相同,否则getty程序将不能正常工作。

  runlevel是init所处于的运行级别的标识,一般使用0-6以及S或s。0、1、6运行级别被系统保留,0作为shutdown动作,1作为重启至单用户模式,6为重启;S和s意义相同,表示单用户模式,且无需inittab文件,因此也不在inittab中出现,实际上,进入单用户模式时,init直接在控制台(/dev/console)上运行/sbin/sulogin。

  在一般的系统实现中,都使用了2、3、4、5几个级别,在Redhat系统中,2表示无NFS支持的多用户模式,3表示完全多用户模式(也是最常用的级别),4保留给用户自定义,5表示XDM图形登录方式。7-9级别也是可以使用的,传统的Unix系统没有定义这几个级别。runlevel可以是并列的多个值,以匹配多个运行级别,对大多数action来说,仅当runlevel与当前运行级别匹配成功才会执行。

  initdefault是一个特殊的action值,用于标识缺省的启动级别;当init由核心激活以后,它将读取inittab中的initdefault项,取得其中的runlevel,并作为当前的运行级别。如果没有inittab文件,或者其中没有initdefault项,init将在控制台上请求输入 runlevel。

  sysinit、boot、bootwait等action将在系统启动时无条件运行,而忽略其中的runlevel,其余的action(不含initdefault)都与某个runlevel相关。各个action的定义在inittab的man手册中有详细的描述。

  在Redhat系统中,一般情况下inittab都会有如下几项:

  id:3:initdefault:

  #表示当前缺省运行级别为3--完全多任务模式;

  si::sysinit:/etc/rc.d/rc.sysinit

  #启动时自动执行/etc/rc.d/rc.sysinit脚本

  l3:3:wait:/etc/rc.d/rc 3

  #当运行级别为3时,以3为参数运行/etc/rc.d/rc脚本,init将等待其返回

  0:12345:respawn:/sbin/mingetty tty0

  #在1-5各个级别上以tty0为参数执行/sbin/mingetty程序,打开tty0终端用于

  #用户登录,如果进程退出则再次运行mingetty程序

  x:5:respawn:/usr/bin/X11/xdm -nodaemon

  #在5级别上运行xdm程序,提供xdm图形方式登录界面,并在退出时重新执行

  rc启动脚本

  上一节已经提到init进程将启动运行rc脚本,这一节将介绍rc脚本具体的工作。

  一般情况下,rc启动脚本都位于/etc/rc.d目录下,rc.sysinit中最常见的动作就是激活交换分区,检查磁盘,加载硬件模块,这些动作无论哪个运行级别都是需要优先执行的。仅当rc.sysinit执行完以后init才会执行其他的boot或bootwait动作。

  如果没有其他boot、bootwait动作,在运行级别3下,/etc/rc.d/rc将会得到执行,命令行参数为3,即执行/etc/rc.d/rc3.d/目录下的所有文件。rc3.d下的文件都是指向/etc/rc.d/init.d/目录下各个Shell脚本的符号连接,而这些脚本一般能接受start、stop、restart、status等参数。rc脚本以start参数启动所有以S开头的脚本,在此之前,如果相应的脚本也存在K打头的链接,而且已经处于运行态了(以/var/lock/subsys/下的文件作为标志),则将首先启动K开头的脚本,以stop作为参数停止这些已经启动了的服务,然后再重新运行。显然,这样做的直接目的就是当init改变运行级别时,所有相关的服务都将重启,即使是同一个级别。

  rc程序执行完毕后,系统环境已经设置好了,下面就该用户登录系统了。

  getty和login

  在rc返回后,init将得到控制,并启动mingetty(见第五节)。mingetty是getty的简化,不能处理串口操作。getty的功能一般包括:

  打开终端线,并设置模式

  输出登录界面及提示,接受用户名的输入

  以该用户名作为login的参数,加载login程序

  注:用于远程登录的提示信息位于/etc/issue.net中。

  login程序在getty的同一个进程空间中运行,接受getty传来的用户名参数作为登录的用户名。

  如果用户名不是root,且存在/etc/nologin文件,login将输出nologin文件的内容,然后退出。这通常用来系统维护时防止非root用户登录。

  只有/etc/securetty中登记了的终端才允许root用户登录,如果不存在这个文件,则root可以在任何终端上登录。/etc/usertty文件用于对用户作出附加访问限制,如果不存在这个文件,则没有其他限制。

  当用户登录通过了这些检查后,login将搜索/etc/passwd文件(必要时搜索 /etc/shadow文件)用于匹配密码、设置主目录和加载shell。如果没有指定主目录,将默认为根目录;如果没有指定shell,将默认为/bin/sh。在将控制转交给shell以前, getty将输出/var/log/lastlog中记录的上次登录系统的信息,然后检查用户是否有新邮件(/usr/spool/mail/{username})。在设置好shell的uid、gid,以及TERM,PATH 等环境变量以后,进程加载shell,login的任务也就完成了。

你可能感兴趣的:(Linux从开机到登录启动过程综述(3))