制作嵌入式根文件系统(常见问题详解)

 

<script type="text/javascript"> document.body.oncopy = function() { if (window.clipboardData) { setTimeout(function() { var text = clipboardData.getData("text"); if (text && text.length>300) { text = text + "/r/n/n本文来自CSDN博客,转载请标明出处:" + location.href; clipboardData.setData("text", text); } }, 100); } } </script> <script type="text/javascript">function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>

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

init 进程是 系统 中所有进程的父进程, init 进程繁衍出完成通常操作所需的子进程,这些操作包括 : 设置机器名、检查和安装磁盘及文件系统、 启动 系统日志、配置网络接口并启动网络和邮件服务,启动打印服务等。 Solaris init 进程的主要任务是按照 inittab 文件所提供的信息创建进程,由于进行系统初始化的那些进程都由 init 创建,所以 init 进程也称为系统初始化进程。
      
下面具体说明 inittab 文件的格式。
   inittab 文件中每一记录都从新的一行开始,每个记录项最多可有 512 个字符,每一项的格式通常如下 :id:rstate:action:process ,下面分别解释。
   1.id 字段是最多 4 个字符的字符串,用来唯一标志表项。
   2.rstate(run state) 字段定义该记录项被调用时的运行级别, 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 文件,可以通过命令 init Q init q 使 init 进程立即重新读取并处理文件 inittab

以上这些都是介绍的标准的 linux System V 的标准,所以对嵌入式来讲有些东西并不见得有用!这里介绍点针对嵌入式的,也就是针对 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 V init 类似,但是, id BusyBox init 中具有不同的意义。对 BusyBox 而言, id 用来指定启动进程的控制 tty 。如果所启动的进程并不是可以交互的 shell ,例如 BusyBox sh ash ),应该会有个控制 tty ,如果控制 tty 不存在, Busybox sh 会报错。 BusyBox 将会完全忽略 runlevel 字段,所以空着它就行了,你也许会问既然没用保留着它干吗,我想大概是为了和传统的 Sytem V init 保持一致的格式吧。 process 字段用来指定所执行程式的路径,包括命令行选项。 action 字段用来指定下面表中 8 个可应用到 process 的动作之一。

动作

结果

sysinit

init 提供初始化命令行的路径

respawn

每当相应的进程终止执行便会重新启动

askfirst

类似 respawn ,不过它的主要用途是减少系统上执行的终端应用程序的数量。它将会促使 init 在控制台上显示“ Please press Enter to active this console ”的信息,并在重新启动之前等待用户按下 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 115200 vt100

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

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 115200 vt100

都是可用的。

 
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

[root@vm-dev rootfs]#

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值