linux中/etc/inittab文件分析

来源:互联网 发布:电力数据网 编辑:程序博客网 时间:2024/06/10 06:17
一、什么是init

  init是Linux系统操作中不可缺少的程序之一。 是一个由内核启动的用户级进程。

  内核启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式来启动其他用户级的进程或服务。所以,init始终是第一个进程(其PID始终为1)。
   
    init进程是系统所有进程的起点,Linux在完成核内引导以后,就开始运行init程序。
     
     init程序需要读取配置文件/etc/inittab。inittab是一个不可执行的文本文件,它有若干行指令所组成。

  内核会在过去曾使用过init的几个地方查找它,它的正确位置(对Linux系统来说)是/sbin/init.如果内核找不到init,它就会试着运行/bin/sh,如果运行失败,系统的启动也会失败。

二、运行级别

  Runlevel 0是让init关闭所有进程并终止系统。

    Runlevel1是用来将系统转到单用户模式,单用户模式只能有系统管理员进入,在该模式下处理那些在有登录用户的情况下不能进行更改的文件,改runlevel的编号1也可以用S代替。
    Runlevel2是允许系统进入多用户的模式,但并不支持文件共享,这种模式很少应用。
    Runlevel3是最常用的运行模式,主要用来提供真正的多用户模式,也是多数服务器的缺省模式。
    Runlevel4一般不被系统使用,用户可以设计自己的系统状态并将其应用到runlevel4阶段,尽管很少使用,但使用该系统可以实现一些特定的登录请求。
    Runlevel5是将系统初始化为专用的XWindow终端。对功能强大的Linux系统来说,这并不是好的选择,但用户如果需要这样,也可以通过在runlevel启动来实现该方案。
    Runlevel6是关闭所有运行的进程并重新启动系统。

The following runlevels aredefined:
   N      System bootup(NONE).
   S      Single user mode (not to beswitched to directly)
   0      halt
   1      single usermode
   2 .. 5  multiuser mode
   6      reboot

这些级别在/etc/inittab 文件里指定。这个文件是init 程序寻找的主要文件,最先运行的服务是放在/etc/rc.d目录下的文件。在大多数的Linux 发行版本中,启动脚本都是位于 /etc/rc.d/init.d中的。这些脚本被用ln 命令连接到/etc/rc.d/rcn.d 目录。(这里的n 就是运行级0-6)

三、运行级别的配置

      在inittab文件中以#开头的所有行都是注释行。注释行有助于用户理解inittab文件,inittab文件中的值都是如下格式:

       label:runlevel:action:process


       1,label是1~4个字符的标签,用来标示输入的值。一些系统只支持2个字符的标签。鉴于此原因,多数人都将标签字符的个数限制在2个以内。该标签可以是任意字符构成的字符串,但实际上,某些特定的标签是常用的,在RedHat Linux中使用的标签是:
id 用来定义缺省的init运行的级别
si 是系统初始化的进程
ln 其中的n从1~6,指明该进程可以使用的runlevel的级别
ud 是升级进程
ca 指明当按下Ctrl+Alt+Del时运行的进程
pf 指当UPS表明断电时运行的进程
pr 是在系统真正关闭之前,UPS发出电源恢复的信号时需要运行的进程

x 是将系统转入X终端时需要运行的进程


2,runlevel字段指定runlevel的级别。可以指定多个runlevel级别,也可以不为runlevel字段指定特定的值。(另外sysinit、boot、bootwait这三个进程会忽略这个设置值。)


3,action:表示进入对应的runlevels时,init应该运行process字段的命令的方式。有效的action值如下:
respawn:表示init应该监视这个进程,即使其结束后也应该被重新启动。
  wait:init应该运行这个进程一次,并等待其结束后再进行下一步操作。
  once:init需要运行这个进程一次。
  boot:随系统启动运行,所以runlevel值对其无效。
  bootwait:随系统启动运行,并且init应该等待其结束。
  off:没有任何意义。
  initdefault:系统启动后的默认运行级别;由于进入相应的运行级别会激活对应级别的进程,所以对其指定process字段没有任何意义。如果inittab文件内不存在这一条记录,系统启动时在控制台上询问进入的运行级。
  sysinit:系统启动时准备运行的命令。比如说,这个命令将清除/tmp.可以查看/etc/rc.d/rc.sysinit脚本了解其运行了那些操作。
  powerwait:允许init在电源被切断时,关闭系统。当然前提是有U P S和监视U PS并通知init电源已被切断的软件。RH linux默认没有列出该选项。
  powerfail:同powerwait,但init不会等待正在运行的进程结束。RHlinux默认没有列出该选项。
  powerokwait:当电源监视软件报告“电源恢复”时,init要执行的操作。
  powerfailnow:检测到ups电源即将耗尽时,init要执行的操作,和powerwait/powerfail不同的哟。
  ctrlaltdel:允许init在用户于控制台键盘上按下Ctrl + Alt +Del组合键时,重新启动系统。注意,如果该系统放在一个公共场所,系统管理员可将Ctrl + Alt +Del组合键配置为别的行为,比如忽略等。我是设置成打印一句骂人的话了^o^.kbrequest:监视到特定的键盘组合键被按下时采取的动作,现在还不完善。
  ondemand:A process marked with an ondemand runlevel will beexecuted whenever the specified ondemand runlevel is called.However, no runlevel change will occur (ondemand runlevels are ‘a’,‘b’,and ‘c’),(英语太菜,那个however不知道该怎么翻译才好。惭愧!)

 

4,process字段包含init执行的进程,该进程采用的格式与在命令行下运行该进程的格式一样,因此process字段都以该进程的名字开头,紧跟着是运行时,紧跟着是运行时要传递给该进程的参数。比如/sbin/shutdown-t3 -r now,该进程在按下Ctrl+Alt+Del时执行,在命令行下也可以直接输入来重新启动系统。

 

四、例子

仔细学习例子文件,学习应用其中关于inittab的语法格式。该文件的大多数内容都可以忽略,因为超过一半的内容都是注释,剩余的一些文件内容主要是用来实现某些特殊的功能:

    id的值表明缺省的runlevel是3。
    ud的值可以唤醒/sbin/update进程,该进程为保持磁盘的完整性,将在对磁盘进行I/O操作之前清空整个I/O缓冲区。
   pf、pr和ca的值只被特定的中断所调用。
   如果系统是专用的X终端,则只需x的输入值。
   getty进程来提供虚拟终端设备的服务,例如:
    3:2345:respawn:/sbin/mingettytty3
   标签字段的值是3,3是设备tty3的数字后缀,tty3与相应的进程相关联,该getty进程可以启动的runlevel是2、3、4和5,当该进程终止时,init马上就重新启动它。启动进程的路径名是/sbin/mingetty,该进程是实现虚拟终端支持的最小版本的getty,为tty3提供启动虚拟设备的进程。
   si::sysinit:/etc/rc.d/rc.sysinit

   该值告诉init程序运行/etc/rc.d/rc.sysinit脚本文件来初始化系统,该脚本文件与所有启动的脚本类似,它只是一个包含Linux的shell命令的可执行文件,注意输入的字符串必须包括该脚本的完整路径。不同版本的Linux存放该脚本的位置也不相同,但不用刻意去记忆这些位置,只需查看/etc/inittab文件即可,该文件中包含启动脚本文件的确切位置。


另一篇文章介绍:

嵌入式系统下的linux启动配置文件,不同与普通的PClinux启动配置,启动相关文件与文件的内容也要少得多。嵌入式系统下的linux启动过程一般是:
    1在bootloader中制定各种要求传给linux内核的参数,制作ramdisk或ramfs文件系统,并在开机后首先mount上,该文件系统主要负责包含启动运行的配置文件,嵌入式系统主要是/etc/inittab和/etc/rc文件;
    2在init进程启动后,进程首先执行/etc/inittab文件,该文件语法下面介绍,一般包括三项内容就可以启动。其中主要的一项内容就是::sysinit:/etc/rc,目的是制定初始化要执行的脚本配置文件,在/etc/rc中则主要是配置系统;另一项内容是::respawn:-/usr/sbin/xxx,xxx一般为shell,最后一个重要的项是::shutdown:/bin/umount-a -r
   接下来的部分为转载http://blog.csdn.net/kernel_32/archive/2009/02/03/3860756.aspx

首先介绍点背景知识,关于inittab的:

init进程是系统中所有进程的父进程,init进程繁衍出完成通常操作所需的子进程,这些操作包括:设置机器名、检查和安装磁盘及文件系统、启动系统日志、配置网络接口并启动网络和邮件服务,启动打印服务等。Solaris中init进程的主要任务是按照inittab文件所提供的信息创建进程,由于进行系统初始化的那些进程都由init创建,所以init进程也称为系统初始化进程。
      下面具体说明inittab文件的格式。
  inittab文件中每一记录都从新的一行开始,每个记录项最多可有512个字符,每一项的格式通常如下:id:rstate:action:process,下面分别解释。
  1.id字段是最多4个字符的字符串,用来唯一标志表项。
  2.rstate(runstate)字段定义该记录项被调用时的运行级别,rstate可以由一个或多个运行级别构成,也可以是空,空则代表运行级别0~6。当请求init改变运行级别时,那些rstate字段中不包括新运行级别的进程将收到SIGTERM警告信号,并且最后被杀死;只有a、b、c启动的命令外(a、b、c不是真正的运行级别)
  3.action字段告诉init执行的动作,即如何处理process字段指定的进程,action字段允许的值及对应的动作分别为:
        1)respawn:如果process字段指定的进程不存在,则启动该进程,init不等待处理结束,而是继续扫描inittab文件中的后续进程,当这样的进程终止时,init会重新启动它,如果这样的进程已存在,则什么也不做。
        2)wait:启动process字段指定的进程,并等到处理结束才去处理inittab中的下一记录项。
        3)once:启动process字段指定的进程,不等待处理结束就去处理下一记录项。当这样的进程终止时,也不再重新启动它,在进入新的运行级别时,如果这样的进程仍在运行,init也不重新启动它。
        4)boot:只有在系统启动时,init才处理这样的记录项,启动相应进程,并不等待处理结束就去处理下一个记录项。当这样的进程终止时,系统也不重启它。
        5)bootwait:系统启动后,当第一次从单用户模式进入多用户模式时处理这样的记录项,init启动这样的进程,并且等待它的处理结束,然后再进行下一个记录项的处理,当这样的进程终止时,系统也不重启它。
        6)powerfail:当init接到断电的信号(SIGPWR)时,处理指定的进程。
        7)powerwait:当init接到断电的信号(SIGPWR)时,处理指定的进程,并且等到处理结束才去检查其他的记录项。
        8)off:如果指定的进程正在运行,init就给它发SIGTERM警告信号,在向它发出信号SIGKILL强制其结束之前等待5秒,如果这样的进程不存在,则忽略这一项。
        9)ondemand:功能通respawn,不同的是,与具体的运行级别无关,只用于rstate字段是a、b、c的那些记录项。
           10)sysinit:指定的进程在访问控制台之前执行,这样的记录项仅用于对某些设备的初始化,目的是为了使init在这样的设备上向用户提问有关运行级别的问题,init需要等待进程运行结束后才继续。
        11)initdefault:指定一个默认的运行级别,只有当init一开始被调用时才扫描这一项,如果rstate字段指定了多个运行级别,其中最大的数字是默认的运行级别,如果rstate字段是空的,init认为字段是0123456,于是进入级别6,这样便陷入了一个循环,如果inittab文件中没有包含initdefault的记录项,则在系统启动时请求用户为它指定一个初始运行级别
  4.Process字段中进程可以是任意的守候进程、可执行脚本或程序。
  另外:在任何时候,可以在文件inittab中添加新的记录项,级别Q/q不改变当前的运行级别,重新检查inittab文件,可以通过命令initQ或init q使init进程立即重新读取并处理文件inittab

以上这些都是介绍的标准的linux SystemV的标准,所以对嵌入式来讲有些东西并不见得有用!这里介绍点针对嵌入式的,也就是针对busybox init的:

busybox的init

  除了基本的命令之外,BusyBox还支持init功能,如同其它的init一样,busybox的init也是完成系统的初始化工作,关机前的工作等等,我们知道在Linux的内核被载入之后,机器就把控制权转交给内核,linux的内核启动之后,做了一些工作,然后找到根文件系统里面的init程序,并执行它,BusyBox的init进程会依次进行以下工作:(参考<<构建嵌入式LINUX系统>>p201)

1.      为init设置信号处理过程

2.      初始化控制台

3.      剖析/etc/inittab文件

4.      执行系统初始化命令行,缺省情况下会使用/etc/init.d/rcS

5.      执行所有导致init暂停的inittab命令(动作类型:wait)

6.      执行所有仅执行一次的inittab(动作类型:once)

一旦完成以上工作,init进程便会循环执行以下进程:

      1.  执行所有终止时必须重新启动的inittab命令(动作类型:once)

      2. 执行所有终止时必须重新启动但启动前必须询问用户的inittab命令(动作类型:askfirst)

      初始化控制台之后,BusyBox会检查/etc/inittab文件是否存在,如果此文件不存在,BusyBox会使用缺省的inittab配置,它主要为系统重引导,系统挂起以及init重启动设置缺省的动作,此外它还会为四个虚拟控制台(tty1到tty4)设置启动shell的动作。如果未建立这些设备文件,BusyBox会报错。

      inittab文件中每一行的格式如下所示:(busybox的根目录下的example文件夹下有详尽的inittab文件范例)     

      id:runlevel:action:process

尽管此格式与传统的Sytem Vinit类似,但是,id在BusyBox的init中具有不同的意义。对BusyBox而言,id用来指定启动进程的控制tty。如果所启动的进程并不是可以交互的shell,例如BusyBox的sh(ash),应该会有个控制tty,如果控制tty不存在,Busybox的sh会报错。BusyBox将会完全忽略runlevel字段,所以空着它就行了,你也许会问既然没用保留着它干吗,我想大概是为了和传统的SytemVinit保持一致的格式吧。process字段用来指定所执行程式的路径,包括命令行选项。action字段用来指定下面表中8个可应用到process的动作之一。

动作
 结果
 
sysinit
 为init提供初始化命令行的路径
 
respawn
 每当相应的进程终止执行便会重新启动
 
askfirst
 类似respawn,不过它的主要用途是减少系统上执行的终端应用程序的数量。它将会促使init在控制台上显示“Pleasepress Enter to active thisconsole”的信息,并在重新启动之前等待用户按下enter键
 
wait
 告诉init必须等到相应的进程完成之后才能继续执行
 
once
 仅执行相应的进程一次,而且不会等待它完成
 
ctratldel
 当按下Ctrl+Alt+Delete组合键时,执行相应的进程
 
shutdown
 当系统关机时,执行相应的进程
 
restart
 当init重新启动时,执行相应的进程,通常此处所执行的进程就是init本身
 

 

以下是我的usblinux的inittab文件

::sysinit:/etc/init.d/rcS

::respawn:/sbin/getty  115200 tty1

tty2::askfirst:-/bin/sh

tty3::askfirst:-/bin/sh

::restart:/sbin/init

::ctrlaltdel:/bin/umount -a -r

这个inittab执行下列动作

1.      将/etc/init.d/rcS设置成系统的初始化文件

2.      在115200 bps的虚拟终端tty1上启动一个登陆会话 (注意getty的用法)

3.      在虚拟终端tty2和tty3上启动askfirst动作的shell

4.      如果init重新启动,将/sbin/init设置成它会执行的程序

5.      告诉init,在系统关机的时候执行umount命令卸载所有文件系统,并且在卸载失败时用只读模式冲新安装以保护文件系统。

 

 

1、busybox的inittab与pc使用的inittab不同,第一ID并不是随便取名字的,这个名字要与/dev/目录下是否有对应的文件对应

对应错误

 

can't open /dev/0: No such file or directory

process '-/bin/sh' (pid 789) exited. Scheduling for restart.

can't open /dev/0: No such file or directory

process '-/bin/sh' (pid 793) exited. Scheduling for restart.

2、出现下面这种错误:

process '-/bin/sh' (pid 789) exited. Scheduling for restart.

process '-/bin/sh' (pid 794) exited. Scheduling for restart.

process '-/bin/sh' (pid 796) exited. Scheduling for restart.

process '-/bin/sh' (pid 798) exited. Scheduling for restart.

对应的inittab文件中有

ttyS0::askfirst:-/bin/sh

虽然在/dev/目录下有ttyS0设备,但是这个设备显然不可用,所以才会出现上面的错误

3、当在inittab中同时定义的两个在同一个串口终端登陆的语句时

::askfirst:-/bin/sh

s3c2410_serial0:23456:respawn:/sbin/getty -L s3c2410_serial0 115200vt100

出现的情况就是被抢占,不能接收任何串口输入

4、bad inittab entry

多半时因为非法字符造成的。

 

5、busybox中的字段runleve也没有运行时的运行级别的概念

 

6、分析一下启动的过程

1.      为init设置信号处理过程

2.      初始化控制台

3.      剖析/etc/inittab文件

4.      执行系统初始化命令行,缺省情况下会使用/etc/init.d/rcS

5.      执行所有导致init暂停的inittab命令(动作类型:wait)

6.      执行所有仅执行一次的inittab(动作类型:once)

一旦完成以上工作,init进程便会循环执行以下进程:

      1.  执行所有终止时必须重新启动的inittab命令(动作类型:once)

      2. 执行所有终止时必须重新启动但启动前必须询问用户的inittab命令(动作类型:askfirst)

      初始化控制台之后,BusyBox会检查/etc/inittab文件是否存在,如果此文件不存在,BusyBox会使用缺省的inittab配置,它主要为系统重引导,系统挂起以及init重启动设置缺省的动作,此外它还会为四个虚拟控制台(tty1到tty4)设置启动shell的动作。如果未建立这些设备文件,BusyBox会报错。

 

7、网上有人问“-”的作用

我很纳闷:
:: respawn:-/bin/sh
这个-是干什么的,为什么有的时候有有的时候没有???
还有啊,我从网上看到一个例程,如下,节选:
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
我搞不清两个的区别,这样控制台就启动了,是第一句启动的还是第二句,那我内核启动参数里面的console=ttyS0会自动来找这个控制台???

原帖由 wavezone 于 2008-8-22 16:34 发表 
我很纳闷:
:: respawn:-/bin/sh
这个-是干什么的,为什么有的时候有有的时候没有???
还有啊,我从网上看到一个例程,如下,节选:
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
我搞不清两个的区别 ...

 

测试的时候是这样的,加上”-”的语句会在登陆终端之后调用/etc/目录下的profile文件,而不加”-”的不会执行这个脚本。

其实登陆终端的命令有几种方便,但是标准的还是使用getty来登陆,但是直接使用如上的语句也是可以的,并且兼容性强一点,因为它不需要指定对应的串口设备。

::askfirst:-/bin/sh

s3c2410_serial0::askfirst:-/bin/sh

::askfirst:-/bin/sh

s3c2410_serial0:23456:respawn:/sbin/getty -L s3c2410_serial0 115200vt100

都是可用的。

 
8./bin/sh: XXX not found
arm-linux-readelf -d xxx
查看你的以用程序依赖哪些库
一般是因为缺少libc.so.6造成的,实际还是根文件系统的问题,没有将常用的库文件拷贝到/lib目录下
常用的库:

[root@centos lib]cp /usr/local/arm/3.4.1/arm-linux/lib/ld* .

[root@centos lib]cp/usr/local/arm/3.4.1/arm-linux/lib/libc-2.3.2.so .

[root@centos lib]cp /usr/local/arm/3.4.1/arm-linux/lib/libc.so.6.

[root@centos lib]cp /usr/local/arm/3.4.1/arm-linux/lib/libm * .

[root@centos lib]cp /usr/local/arm/3.4.1/arm-linux/lib/libcrypt*.

9、错误insmod: chdir(2.6.26.6): No such file or directory

网上有人提出这种解决方法:

需要注意的是insmod等模块加载命令需要从lib/modules/2.6.26.6

的目录下加载模块,所以必须先建立此目录,然后将模块放到此目录下面,否则将出现以下两种情况:

一是没有建立lib/modules/2.6.26.6目录,取决于内核版本号,将出现insmod: chdir(2.6.26.6):No such file or directory的错误

二是只将模块简单地放在根目录或其它文件夹,没有将其拷贝到指定的lib/modules/2.6.26.6目录,将出现

insmod: module 'gpio_driver' not found错误

不过这种方法不是很奏效

 

根本原因是insmod的问题,在busybox编译的时候参考下面的选项,不要使用

Linux Module Utilities --->

  [ ] Simplified modutils

//该选项不要选择

[*] Support version 2.6.x Linux kernels 

//此选项选上

参考如下:

 

 


 

 

10、不能执行”-h”命令

在执行xxx –h时没有任何反应。是在lib目录下缺少常见的库文件

参考如下:

[root@vm-dev rootfs]# ls lib/

ld-2.3.6.so              libc-2.3.6.so     libgcc_s.so     libnsl.so.1            libnss_files.so.2       libnss_nis.so.2    librt-2.3.6.so      libthread_db.so.1

ld-linux.so.2            libcrypt-2.3.6.so libgcc_s.so.1   libnss_compat-2.3.6.so libnss_hesiod-2.3.6.so  libpcprofile.so    librt.so.1          libutil-2.3.6.so

libanl-2.3.6.so          libcrypt.so.1     libm-2.3.6.so   libnss_compat.so.2     libnss_hesiod.so.2      libpthread-0.10.so libSegFault.so      libutil.so.1

libanl.so.1              libc.so.6         libmemusage.so  libnss_dns-2.3.6.so    libnss_nis-2.3.6.so     libpthread.so.0    libtermcap.so.2     modules

libBrokenLocale-2.3.6.so libdl-2.3.6.so    libm.so.6 libnss_dns.so.2        libnss_nisplus-2.3.6.so libresolv-2.3.6.so  libtermcap.so.2.0.8

libBrokenLocale.so.1     libdl.so.2        libnsl-2.3.6.so libnss_files-2.3.6.so  libnss_nisplus.so.2     libresolv.so.2     libthread_db-1.0.so



 

一份完整的inittab文件

引用内容:
    #
    inittab       This file describes how the INIT process should set up
                  the system in certain run-level.
    #
    Author:       Miquel van Smoorenburg, 
                  Modified for RHS Linux by Marc Ewing and Donnie Barnes
    #
                                                                                                                             
    Default runlevel. The runlevels used by RHS are:
      halt (Do NOT set initdefault to this)
      Single user mode
      Multiuser, without NFS (The same as 3, if you do not have networking)
      Full multiuser mode
      unused
      X11
      reboot (Do NOT set initdefault to this)
       
    id:3:initdefault:
                                                                                                                             
    System initialization.
    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


    Things to run in every runlevel
    ud::once:/sbin/update
                                                                                                                             
    Trap CTRL-ALT-DELETE
    ca::ctrlaltdel:/sbin/shutdown -t3 -r now
                                                                                                                             
    When our UPS tells us power has failed, assume we have few minutes
    of power left.  Schedule shutdown for minutes from now.
    This does, of course, assume you have powerd installed and your
    UPS connected and working correctly.
    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"


    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
    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
                                                                                                                             
    Run xdm in runlevel 5
    x:5:respawn:/etc/X11/prefdm -nodaemon
0 0
原创粉丝点击