详解:init进程

时间:2016-12-16 16:30来源:凌阳教育 作者:larran 点击:
  init进程是内核启动的第一个用户级进程,它有许多很重要的任务,比如象启动getty(用于用户登录)、实现运行级别、以及处理孤立进程。
 
  什么时候我们最关注init
  对于Linux系统的运行来说,init程序是最基本的程序之一。但你仍可以大部分的忽略它。一个好的Linux发行版本通常随带有一个init的配置,这个配置适合于绝大多数系统的工作,在这样一些系统上不需要对init做任何事。通常,只有你在碰到诸如串行终端挂住了、拨入(不是拨出)调制解调器、或者你希望改变缺省的运行级别时你才需要关心init。
 
  为什么init是第一个进程?
当内核启动了自己之后(已被装入内存、已经开始运行、已经初始化了所有的设备驱动程序和数据结构等等),通过启动用户级程序init来完成引导进程的内核部分。因此,init总是第一个进程(它的进程号总是1)。
 
  系统的简单启动过程
  内核在几个位置上来查寻init,这几个位置以前常用来放置init,但是init的最适当的位置(在Linux系统上)是/sbin/init。如果内核没有找到init,它就会试着运行/bin/sh,如果还是失败了,那么系统的启动就宣告失败了。当init开始运行,它通过执行一些管理任务来结束引导进程,例如检查文件系统、清理/tmp、启动各种服务以及为每个终端和虚拟控制台启动getty,在这些地方用户将登录系统。在系统完全起来之后,init为每个用户已退出的终端重启getty(这样下一个用户就可以登录)。
  init同样也收集孤立的进程
当一个进程启动了一个子进程并且在子进程之前终止了,这个子进程立刻成为init的子进程。对于各种技术方面的原因来说这是很重要的,知道这些也是有好处的,因为这便于理解进程列表和进程树图。
 
  Init的变种
  init的变种很少,绝大多数Linux发行版本使用sysinit(由Miguel van Smoorenburg著),它是基于System V的init设计。UNIX的BSD版本有一个不同的init。最主要的不同在于运行级别:System V有而BSD没有(至少是传统上说),在此我们仅讨论sysvinit。
  配置init以启动getty
  当init启动后,init读取/etc/inittab配置文件。当系统正在运行时,如果发出HUP信号,init会重读它——这个特性就使得对init的配置文件作过的更改不需要再重新启动系统就能起作用了。
  etc/inittab中的行由四个冒号限定的域组成:id:runlevels:action:process
/etc/inittab可以包含空行以及以数字符号(’#’)开始的行,这些行均被忽略。
 
  下面对各个域进行了描述:
  lid 唯一确定文件中的一行。对于getty行来说,id指定了它在其上运行的终端(id也就是设备文件名/dev/tty后面的字符)。
  lrunlevels 该行应考虑的运行级别。运行级别以单个数字给出,没有分隔符。
  laction 对于该行应采取的动作。
  lprocess 要运行的命令。
  为了在第一个虚拟终端上(/dev/tty1)运行getty、在所有的正规多用户运行级别中(2-5),应该写入下面这行:
  1:2345:respawn:/sbin/getty 9600 tty1
  l第一个域指出这是对应于/dev/tty1的行。
  l第二个域说明它应用于运行级别2,3,4和5。
  l第三个域respawn是说在命令退出之后,应被再次执行(因此,用户可以登录、退出并且再次登录)。
  l最后一个域是在第一个虚拟终端上运行getty的命令。
  但是如果一个命令运行时失败了,并且init配置成重运行它,它会使用许多的系统资源:init运行它、它失败了、init再运行它、再次失败等等,没完没了——为了避免这样,init将追踪一个命令重运行了多少次,并且如果重运行的频率太高,它将被延时五分钟后再运行。
如果你需要给系统增加终端或者拨入调制解调器线路,你应该给/etc/inittab增加更多的行,每一行对应一个终端或一条拨入线(详细信息,参见init、inittab以及getty的manual page)。
 
  运行级别
  一个运行级别(run level)是init以及整个系统的状态,它定义了能够提供什么系统服务。
  对于如何使用用户定义运行级别(2到5)没有一致的意见。在Linux中初始化脚本在/etc/inittab 文件(或称初始化表)中可以找到关于不同运行级别的描述。其描述如下:
  # Default runlevel. The runlevels used by RHS are:
  # 0 - halt (Do NOT set initdefault to this)
  # 1 - Single user mode
  # 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
  # 3 - Full multiuser mode
  # 4 - unused
  # 5 - X11
  # 6 - reboot (Do NOT set initdefault to this)
  中文释义:
  l0 终止系统
  l1 单用户模式(用于特别管理)
  l2-5 正常操作(用户定义)
  l6 重启动
  运行级别通过如下行所示的行在/etc/inittab中配置:
  l2:2:wait:/etc/init.d/rc 2
  l第一个域是任意给的符号——level 2的所写
  l第二个域指出是运行级别2
  l第三个域说明:当进入该运行级别时,init运行第四个域中的命令一次,并且init等待该命令它的结束。
l第四个域中的命令是用来做一个运行级别的所有设置工作。它将启动还没有运行的服务,停止在新的运行级别中不应再运行的服务。
 
  默认运行级别
  当init开始运行时,它在/etc/inittab中查寻一行,该行指定了缺省的运行级别:
  id:2:initdefault:
通过给内核一个single或emergency命令行参数,你可以在init运行开始时转到一个非缺省的运行级别上。例如,内核命令行参数可以通过LILO给出。这使得你可以选择单用户模式(运行级别 1)。当系统正在运行时,telinit(或者init命令)命令可以改变运行级别——当运行级别改变时,init就运行/etc/inittab中相应的命令。
 
  /etc/inittab中的特殊配置
  /etc/inittab有些特殊的特性,它允许init对特别的环境作出响应。这些与众不同的特性在第三个域中由关键字标出。例子如下:
  lpowerwait 当系统电源失败时,允许init关闭系统。这里假设使用了UPS以及用于监视UPS和通知init电源失败的软件。
  lctrlaltdel 当用户在控制台上按了ctrl-alt-del组合键时,允许init重新(启动)引导系统。
  lsysinit 当系统引导时要执行的命令。例如,这个命令通常是清理/tmp。
上面所列并不是全部,对于所有的关键字以及如何使用它们可以参见inittab的manual page。
 
  进入单用户模式
一个很重要的运行级别是单用户模式(single user mode)(运行级别1),在这个模式中只有系统管理员在使用机器并且只有很少的系统服务在运行,如登录服务。对于一些管理任务来说单用户模式是必须的,如在/usr分区上运行fsck,因为这需要该分区没被加载,除非几乎所有的系统服务都被终止了,否则不可能会有这种情况。
 
  通过telinit请求运行级别1,一个运行着的系统可以转换到单用户模式。在启动时,可以通过在内核的命令行上给出single或emergency来进入单用户模式:内核同样也将命令行给init,init会理解那个单词并且不会使用缺省的运行级别。(内核命令行输入的方法依赖于系统是如何引导的。)在加载文件系统之前,引导进入单用户模式有时是需要的,这样就可以手工运行fsck命令了,否则的话很可能损坏/usr分区(在一个有问题的文件系统上的任何操作会更进一步地损坏它,所以fsck要尽早地运行)。如果启动时fsck的自动检查失败了,启动描述文件init就会自动地进入单用户模式。这是试图避免系统使用一个文件系统,这个文件系统损坏的太严重以至于fsck都不能够自动地修复它。这样的毁坏情况是相当少的,通常是硬盘有问题或是在试验一个内核版本,但是有准备总比没有好。作为一个安全措施,一个正确配置的系统应该在运行单用户模式的shell之前要求口令。否则的话,只要给LILO输入适当的一行参数就很容易地以root身份进入系统。(当然,如果由于文件系统的问题而使/etc/passwd毁坏时,就不是这样了。如果是这样的话,你手头最好有张引导软盘。)
分享到: