使用busybox制作rootfs

  
1  获取源码解压
从busybox的官方主页http://www.busybox.net ,下载busybox的源码,目前最新的版本为busybox-1.13.3.tar.bz2
#tar –jvxf busybox-1.13.3.tar.bz2
进入解压后的busybox源码目录
#cd busybox-1.13.3
2  配置busybox
步骤跟编译linux内核时很像
#make menuconfig
出现一个图形界面,选择Busybox Settings,这里可以对编译、安装以及调试等模式进行配置。
然后选择Build Options,对交叉编译器以及编译方式进行配置。
其中的第一项是Build Busybox as a static binary(no shared libs),如果选择上,则busybox将以静态形式进行编译,否则将以动态方式编译。此外,还需要对交叉编译环境进行配置,选择其中的Cross Compiler Perfix,输入交叉编译器的前缀,我们的嵌入式平台上使用的是arm-uclinux-linux的交叉编译工具。
这里我们先选择静态编译,动态方式的稍后再讲,注意Build with Large File Support (for accessing files > 2 GB)不要选(默认是选上的),否则编译后会出现如下错误:
miscutils/lib.a(readahead.):In function ‘readahead_main’
readahead.(.text.readahead_main+0×70):undefined reference to ‘readahead’
collect2:ld returned 1 exit status
make :***[busybox_unstripped ]Error 1
 
3         编译busybox
#make
4         安装busybox
#make install
可以采用perfix参数安装到指定目录下,格式为:make install prefix=xxx目录,如果不特别指定,将默认在busybox源码目录下生成一个_install目录。到此,busybox基本上可以功成身退 了。我们需要的就是busybox编译出来的这个_install目录。
进入_install目录,可以看到一共有3个目录和一个文件,分别是:bin、sbin和usr目录以及linuxrc文件。
在对这几个目录进行说明之前,先简单介绍一下编译生成的busybox可执行文件,它存在于bin目录下。Busybox使用了带参的main 函数:int main(int argc,char *argv[]),在这个定义中,argc是传递进来的参数的个数(参数数量),而argv是一个字符串数组,代表从命令行传递进来的参数。argv的索 引0是命令行调用的程序名。可以在bin目录下进行如下操作:
#busybox pwd(注意,busybox这个可执行文件不需要加./)
当为一个可执行程序创建符号链接后,在执行这个符号链接时,就可以获取到这个符号链接的名字。而busybox正是使用符号链接的方式使一个可 执行程序看起来像很多程序一样。对于busybox中包含的每个工具来讲,都会创建一个符号链接,这样就可以使用这些符号链接来调用busybox了。然 后busybox接着根据argv[0]的值来调用内部工具。
下面分别对install目录下的几个文件进行一些说明。
Ø        bin包含用户工具,其中,busybox可执行文件就在这个目录 下,该目录下其他所有文件都是指向busybox的符号链接
Ø        sbin目录包含操作系统工具,同样也指向busybox。
Ø        linuxrc是一个链接文件,指向busybox。
5         添加etc目录及基本配置文件
参考一个正常的linux系统将会发现,此时busybox建立的文件系统还缺少很多文件。如果用这个作为文件系统,将是无法运行的。生成这些 配置可以选择的方法有2种,一种是直接从一个正常运行的系统中拷贝,另一种是借助于busybox的examples。显然,选择第二种会容易的多,我们 直接拷贝examples/bootfloopy/etc到install目录下。
#cp –a ../examples/bootfloppy/etc/ .
然后可以看看etc目录下的文件,一共有3个目录和文件,下面逐一对以上几个文件进行分析和说明。
Ø        inittab文件:系统启动后访问的第一个脚本文件,后续启动的文 件都由它指定。下面看一下busybox中原始的inittab文件内容:
::sysint:/etc/init.d/rcS
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount –a -r
其中第一行指定系统的启动脚本为/etc/init.d/rcS
第二行指定打开一个登录会话
第三行指定在第三个虚拟终端打开一个无须登录验证的shell
第四行指定了当按下ctrl+alt+del组合键时的执行命令
Ø        fstab文件:定义了文件系统的各个“挂载点”,需要与实际的系统 相配合。默认的fstab文件内容为:
proc   /proc proc defaults 0 0
其他的根据需要再进行添加,比如devpts  /dev/pts devpts defaults 0 0就是为UNIX PTYs准备的,后面讲telnetd时要用到。
Ø        profile文件:终端登陆之后首先运行的脚本。
 
6         添加dev目录及基本设备文件
调试时要通过串口发送消息到终端显示。因此串口控制台和终端2个设备文件是必不可少的。
#mkdir dev
#mknod dev/console c 5 1
#mknod dev/ttyAMA0 c 204 64
在启动参数中,设置console=ttyAMA0
7         添加其他常用目录
可以选择home、root、proc、mnt、lib、var、opt、tmp。
此时,一个基本的文件系统的功能就已经完成了。可以采用NFS进行调试。但是,此时你可能会遇到如下问题,系统登录后终端上会不断打印:
cannot open /dev/ttyS2:No such file or directory.
原因出在/etc目录下的inittab文件,我们看一下其内容:
::sysint:/etc/init.d/rcS
::respawn:-/bin/sh
tty2::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount –a -r
这条语句表示在第3个虚拟终端打开一个无须登录验证的shell。而我们之前没有建立这个tty2设备,因此会出错。解决的办法有2个:一是屏 蔽该语句,二是建立该设备节点。我们选择将其屏蔽。
8         相关问题
8.1      使用动态方式编译 busybox
进入Build Options时,不要选择Build Busybox as a static binary,其他所有操作步骤跟静态编译一样,你会发现这样建立的文件系统无法启动,终端上打印出如下消息:
Kernel panic-not synving:No init found. Try passing init=option to kernel.
为什么会出现这种问题呢?这就得回到两种编译方式的特点上来。静态编译时是将所用到的库文件一起编译了进去,而动态编译时是在需要时才调用相应 的库。我们选择动态编译后,没有添加任何库文件就运行,显然是会出错的。那么如何查看busybox可执行文件里使用的库呢。Readelf这个工具提供 了解决办法。使用如下命令,参数d表示将文件中所有的动态部分予以显示。
# arm-uclibc-linux-readelf -d busybox 
Dynamic section at offset 0xca014 contains 18 entries:
  标记        类型                         名称/值
 0×00000001 (NEEDED)                     共享库: [libm.so.0]
 0×00000001 (NEEDED)                     共享库: [libc.so.0]
 0×0000000c (INIT)                       0xbe24
 0×0000000d (FINI)                       0xb2054
 0×00000004 (HASH)                       0×80e8
 0×00000005 (STRTAB)                     0xa500
 0×00000006 (SYMTAB)                     0×8b70
 0×0000000a (STRSZ)                      3259 (bytes)
 0×0000000b (SYMENT)                     16 (bytes)
 0×00000015 (DEBUG)                      0×0
 0×00000003 (PLTGOT)                     0xda0cc
 0×00000002 (PLTRELSZ)                   3040 (bytes)
 0×00000014 (PLTREL)                     REL
 0×00000017 (JMPREL)                     0xb244
 0×00000011 (REL)                        0xb1bc
 0×00000012 (RELSZ)                      136 (bytes)
 0×00000013 (RELENT)                     8 (bytes)
 0×00000000 (NULL)                       0×0
从上面的结果中,我们可以看到,busybox这个程序使用到了libm.so.0和libc.so.0两个库文件,实际上这是2个符号链接, 分别指向libc-0.9.28.so和libuClibc-0.9.28.so。将以上四个文件分别拷贝到lib目录下。按理说,这样应该就可以了,但 是仍然无法正常运行。显示的错误信息和刚刚没加库之前一样。可能的原因有2种:一是库文件没有添加全,二是库文件没有正确被加载。根据readelf显示 的结果应该不是第一种原因。那么到底为什么没被正确加载呢?原来库文件的加载,还需要一个共享库加载器。找到对应的文件ld-uClibc- 0.9.28.so和ld-uClibc.so.0添加到lib目录下后。运行正常。
8.2      终端登录用户验证功 能添加
需要在etc目录下增加passwd、group和shadow(在编译busybox时如果不选择shadow功能将不需要这个文件)3个文 件。
生成这3个文件的方法有:
Ø        手动生成,按照格式规范自己编写内容;
Ø        通过busybox提供的工具adderuser自动生成
8.2.1        手动方式
首先我们介绍一下如何手动添加。以增加root用户为例,增加passwd文件,其内容为:
#cat passwd
root:x:0:0:root:/root:/bin/sh
同时,此时要确定root目录已经存在。
passwd一共由7个字段组成,6个冒号将其隔开。它们的含义分别为:
1     用户名
2     是否有加密口令,x表示有,不填表示无,采用MD5、DES加密。
3     用户ID
4     组ID
5     注释字段
6     登录目录
7     所使用的shell程序
增加group文件,其内容为:
#cat group
root:x:0:
Group一共由4个字段组成,3个冒号将其隔开,它们的含义分别为:
1     组名
2     是否有加密口令,同passwd
3     组ID
4     指向各用户名指针的数组
由于busybox默认启动了shadow模式,因此需要增加shadow文件,其内容为:
#cat shadow
root:$1$3jZ93Mwq$oaeef6lWIuThavs8wD0Wh1:0:0:99999:7:::
shadow一共由9个字段组成,8个冒号将其隔开,它们的含义分别为:
1     用户名
2     加密后的口令,若为空,表示该用户不需要口令即可登陆,若为*号,表示该账号被禁用。 上面的表示的是123456加密后的口令。
3     从1970年1月1日至口令最近一次被修改的天数
4     口令在多少天内不能被用户修改
5     口令在多少天后必须被修改(0为没有修改过)
6     口令过期多少天后用户账号被禁止
7     口令在到期多少天内给用户发出警告
8     口令自1970年1月1日被禁止的天数
9     保留域
这里强调一下shadow文件的由来。/etc/passwd文件对系统的所有用户都是可读的,这样的好处是每个用户都知道系统上有哪些用户, 但缺点是其他用户的口令容易受到攻击,尤其是当口令较简单时。所以一些linux系统中使用到了影子口令文件shadow,将用户的口令存储在另一个文件 /etc/shadow中,该文件只有根用户root可读,大大提高了安全性。
不过,采用这种手动添加文件的方法有一个缺陷,就是如果要为用户设置登陆口令的话,shadow文件中必须填写加密后的口令,而这个加密算法我 们又不知道,即使知道,要经过转换后再添加,比较麻烦。此时,不妨试一下第二种方法。
8.2.2        自动方式
自动生成是使用了busybox提供的adduser工具和passwd工具。
在文件系统正常运行起来后,使用adduser命令,使用方法为:
#adduser root
然后就会在etc目录下自动生成passwd 、group和shadow3个文件。但是运行该命令后会打印出如下消息:
passwd:unknown uid 0
这表示不能为该用户设置密码,此时你会发现要passwd命令也无法使用。
解决的办法是,打开passwd文件,其内容为:
root:x:1000:1000:Linux User…:/home/root:/bin/sh
将用户ID和组ID均更改为0
打开group文件,其内容为:
root:x:1000:
同样将组ID改为0
然后,passwd命令就可以正常使用了。这时为root用户设置口令:
#passwd root
根据提示输入密码。其中,root用户登陆后的目录可以手动进行更改。
8.3      telnetd功能 添加
busybox默认已经添加了对telnetd和telnet功能的支持,只需要完成一些相关的设置工作就可以启动这2个功能了。
Ø          创建/dev/pts目录
Ø        在/etc/fstab中添加如下信息,挂载devpts文件系统
devpts /dev/pts devpts defaults 0 0
Ø        在/dev目录下增加ptmx设备文件:
#mknod ptmx c 5 2
Ø        在rcS文件中添加如下脚本,启动telnetd
if [ -x /usr/sbin/telnetd ] ;
then
        telnetd&
fi
Ø        在/dev目录下增加null设备文件,否则上述脚本运行时会出错: 提示找不到null文件。
#mknod null c 1 3
此时,telnetd功能开机就可以启动了。
(yzlworld)




本站文章除注明转载外,均为本站原创或编译
欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。
转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net]
本文标题:使用busybox制作rootfs

本文地址:http://www.rosoo.net/a/201207/16166.html









http://blog.163.com/jlz_325/blog/static/191740009201177014049/

1、BusyBox简介

BusyBox 是很多标准 Linux 工具的一个单个可执行实现。BusyBox 包含了一些简单的工具,例如 cat 和 echo,还包含了一些更大、更复杂的工具,例如 grep、find、mount 以及 telnet;有些人将 BusyBox 称为 Linux 工具里的“瑞士军刀”。

BusyBox 揭露了这样一个事实:很多标准 Linux 工具都可以共享很多共同的元素。例如,很多基于文件的工具(比如 grep 和 find)都需要在目录中搜索文件的代码。当这些工具被合并到一个可执行程序中时,它们就可以共享这些相同的元素,这样可以产生更小的可执行程序。实际上,BusyBox 可以将大约 3.5MB 的工具包装成大约 200KB 大小。这就为可引导的磁盘和使用 Linux 的嵌入式设备提供了更多功能。我们可以对 2.4 和 2.6 版本的 Linux 内核使用 BusyBox。

我们平时用的那些Linux命令就好比是分立式的电子元件,而BusyBox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍,在嵌入式linux应用中,BusyBox有非常广的应用。

2、BusyBox的用法

  可以这样用BusyBox

  #busybox ls

  他的功能就相当运行ls命令

  最常用的用法是建立指向BusyBox的链接,不同的链接名完成不同的功能.

  #ln -s busybox ls

  #ln -s busybox rm

  #ln -s busybox mkdir

  然后分别运行这三个链接:

  #./ls

  #./rm

  #./mkdir

  就可以分别完成了ls、rm和mkdir命令的功能.虽然他们都指向同一个可执行程序BusyBox,但是只要链接名不同,完成的功能就不同, BusyBox就是这么的神奇。

3、配置编译BusyBox

? 下载

首先需要下载BusyBox源代码。可从http://busybox.net上直接下载最新版BusyBox。例如当前最新版为1.5.1。

? 解压:

tar xvf busybox-1.5.1.tar.bz2

? 配置

BusyBox的配置程序和Linux内核菜单配置方式简直一模一样,十分方便易用。使用make menuconfig命令就可以进行配置。

使用busybox制作rootfs_第1张图片

配置过程主要有几点需要修改的:

l 因为我们要将BusyBox交叉编译成ARM可执行程序放在开发板上执行,所以需要使用交叉编译器arm-linux-gcc来编译BusyBox。所以需要修改BusyBox根目录下的Makefile,找到

ARCH ?= $(SUBARCH)

CROSS-COMPILE ?=

修改成ARM的配置,如下:

ARM ?= arm

CROSS-COMPILE ?= arm-linux-

l 在BusyBox配置界面里修改几个配置:

Busybox Settings --->

Build Options

Build BusyBox as a static binary (no shared libs)

这个选项是一定要选择的,这样才能把BusyBox编译成静态链接的可执行文件,运行时才独立于其他函数库,否则必须要其他库文件才能运行。

Busybox Settings --->

Installation Options

Don’t use /usr

这个选项也是要选上的,否则make install 后BusyBox将安装在原系统的/usr下,这将覆盖系统原有的命令。选择这个选项后,make install后会在BusyBox目录下生成一个叫_install的目录,里面有BusyBox和指向他的链接。

Init Utilities --->

init

这个选项最好选上,这样BusyBox就可以初始化脚本inittab,可以用来初始化Linux系统。

如果要让BusyBox包含一个可以用于解释Linux命令的shell,需要配置BusyBox的Shells选项里的内容:

Shells --->

这里可选的shell有多种,包括ash,hush,lash,msh。最好使用ash,因为它是功能最全也最类似于一般Linux系统中的BASH的。同时注意第一行的:

Choose your default shell (none) --->

这里需要回车进去选择默认的Shell,例如选择了ash后,第一行的内容就会变成:

Choose your default shell (ash) --->

这样BusyBox才会生成sh的链接并且将这个sh指向对应的shell(ash)。

l 其他选项都是一些Linux基本命令选项,可以根据自己的需要选择配置,第一次的话用默认的设置即可。

? 编译

如果配置好了BusyBox,就可以使用make命令编译了。

#make

#make install

默认情况下,make install完成后会在BusyBox目录下创建一个新的本地子目录 _install,其中包含了基本的 Linux 环境。在这个目录中,会有一个链接到 BusyBox 的 linuxrc 程序。这个 linuxrc 程序在构建安装盘或急救盘(允许提前进行模块化的引导)时非常有用。同样在这个目录中,还有一个包含操作系统二进制文件的 /sbin 子目录。还有一个包含用户二进制文件的 /bin 目录。在构建软盘发行版或嵌入式初始 RAM 磁盘时,可以将这个 _install 目录迁移到目标环境的根目录中。

4、制作完整的根文件系统

BusyBox虽然为我们创建了Linux根系统中最基本的shell和一些常用命令,但是一个根文件系统还不只包含这些,还需要其它的一些内容。

? 创建一个比较完整的根文件系统目录结构

本章第一节已经介绍了根文件系统中的一些目录,这些目录是Linux正常运行时所必需的。我们可以在BusyBox的_install基础上创建完整的根文件系统目录,一般步骤如下:

l 在PC上创建一个目标根文件系统的目录,例如/rootfs,将BusyBox里的_install目录里所有内容复制到这个文件夹里:cp –r _install /rootfs

l 在/rootfs下创建目录etc/,dev/,lib/,tmp/,usr/,var/目录,同时var/目录里还需要创建var/run和var/log等目录。

l 生成etc/里的设备文件,例如tty,console,fb(FrameBuffer),mtdblock(Memory Technology Device)等,这些设备文件是Linux很多驱动程序及就用程序正常的工作的基础。这些设备文件都是与相应的硬件相联系的,主要包含几种信息:设备类型,主设备号,次设备号。

其中设备类型主要包括字符设备(Character Device)和块设备(Block Device),字符设备主要字符的输入输出设备如键盘、鼠标等,块设备主要指整块数据的输入输出设备,如FLASH、硬盘等存储设备,一般包含缓冲区机制。

主设备号用来区分不同种类的设备,而次设备号用来区分同一类型的多个设备。对于常用设备,Linux有约定俗成的编号,如硬盘的主设备号是3,而次设备对应到每个具体的设备上,一般在/proc/devices文件里可以找到相关信息。

对于一个已存在的设备文件可以通过ls –l 命令来获取它的设备相关信息。

ls  –l  /dev/console

crw-rw---- 1 root root 5,1 Apr 14 23:08 /dev/console

可以看出第一个字母为c,这代表/dev/console是字符设备,若第一个字母为b,则为块设备。而root之后的 5,1就分别为相应设备的主次设备号了。

这里需要强调一点,设备文件类似于配置文件,存储的是一些设备信息,里面不包含特定平台下的指令,所以设备文件本身是平台无关的,也就是说在I386上创建的设备文件可以放在ARM的根文件系统,而可以被Linux正确识别的。

基本了解设备后,还需要如何创建它们,一般情况下可以使用mknod生成相应设备文件。mknod是Linux中用来创建设备文件的命令,格式如下:

mknode [–m MODE] NAME TYPE [MAJOR MINOR]

其中MODE用于指定设备文件的访问权限。NAME为设备文件的文件名,TYPE为相应的设备类型(字符设备c,块设备b等),MAJOR和MINOR分别为主次设备号。

例如要创建刚才的那个console命令可用如下的命令:

mknode –m 660 console c 5 1

设备文件的创建除了使用mknod命令,还可以使用MAKEDEV命令,MAKEDEV可以较方便的创建一系统的设备文件,一般的Linux发行版都有自带,其基本格式如下:

MAKEDEV –d directory -m maxdevices device

其中directory为设备文件的目标存放文件夹,若不指定则为当前系统下的/dev里。maxdevices为最大的设备数,因为MAKEDEV一般会创建一种设备的一系列设备文件,一般从0开始编号,直到maxdevices,所以一般这个需要指定,要不会生成较多的相关设备文件,而一般我们是不需要这么多的。最后一个参数device为对应的设备文件名,包括tty,vt,mem,null,zero,fd,hd,audio,sound等。这些参数的详细内容以及更多的参数选项,可以参考man手册。

可以这样创建硬盘的设备文件hd

MAKEDEV –d /rootfs/dev -m 2 hda

这条命令就会在/rootfs/dev目录中创建hda和hda1两个设备文件,指向第一块硬盘和第一块硬盘的第一个分区。

对于目标根文件系统中的设备文件,一般都应放在etc/目录中,可以用如下几种方法来获取相应的设备文件:

ü 可以手动用mknod命令一个个的创建设备文件;

ü 可以使用MAKEDEV来创建设备文件;

ü 甚至可以直接拷贝PC系统中部分设备文件至目标根文件系统中。

l 构建lib/目录。lib/目录放的是Linux就用程序所需的库文件,其实也是目标平台的指令代码,所以这里的文件与etc/里不一样,必须与相应的硬件平台相对应,例如i386里的库文件放到ARM系统中就不能使用的,这点与Linux的可执行文件一样。在PC机上使用ls /lib命令就可以看到很多.so结尾的库文件,这些.so文件就是Linux的动态链接库(类似于Windows下的DLL文件)。要注意的是.so文件名后缀还可能加上一些版本号标志例如.so.1,.so.1.2等都是动态链接库。

ü 目标根文件系统中的库文件从哪里来?

一般这些库都是事先编译好的,而且跟编译器相关的(glibc等),例如我们使用arm-linux-gcc进行编译则需要相应版本的一些库文件,这些库文件可以从编译器所在的目录里直接拷贝。对于ELDK开发包,可以从ELDK目录下的arm/lib/目录里复制相应文件。

ü 目标根文件系统需要哪些基本库文件?

库文件实际上是由其它可执行文件来调用的,所以库文件的取舍是由根文件系统中所包含的可执行文件来决定的。但是要运行可执行文件,一般有几个是系统必须的。它们是ld(ld-linux),libc,几乎所有的可执行文件都需要调用到这两个库文件。

ld(ld-linux):ld-linux.so 实际上就是一个可执行程序。这是负责执行动态装载的代码。它从可执行程序读取头信息(ELF格式的),然后通过这些信息判断必要的库和需要装载的库。之后,执行动态链接,修改可执行程序和装载的库中的所有地址指针,使程序能够运行。一般的文件名可能为ld-2.3.2.so,ld-linux.so.2,这点与编译器和系统版本有关。

libc:libc.so.6 是以 ld-linux.so.2 为基础架构而完成的动态链接库,它几乎负责了所有常用的标准 C 函数库,例如 Linux 下写的 Socket 程序,其中的connect()、bind()、send() .....之类的函数,都是由 libc.so.6 所提供的。

所以一个最基本的lib/目录应该至少包含这ld-linux.so.2和libc.so.6这两个文件。

ü 应用程序需要哪些库文件?

前面已经说过动态链接库是由应用程序(可执行文件)调用的,那对于一个特定的可执行文件是如何判断它需要哪些库文件的?一般可以编译器的ldd命令来查看,例如arm-linux-gcc包含了arm-linux-ldd命令用来查看ARM可执行文件调用的动态链接库。arm-linux-ldd的功能就是列出可执行文件及动态链接库运行时需要的库文件,例如,对于刚才所指的libc.so.6可以查找出其需要的动态链接库。这里我们假设为ELDK里的libc。

# file /eldk/arm/libc.so.6

libc.so.6:symbolic link to `libc-2.3.5.so`

通过file命令看出这里的libc.so.6实际上是个符号连接,链接到libc-2.3.5.so,所以我们继续追查libc-2.3.5.so:

#file libc-2.3.5.so

libc-2.3.5.so: ELF 32-bit LSB shared object, ARM, version 1(ARM), stripped

从这里可以明显的看出这个是ARM的Shared Object,也就是ARM格式的动态链接库。到这里可以判断出libc.so.6是ARM指令的。下来看libc.so.6到底需要哪些库文件:

#arm-linux-ldd libc.so.6

ld-linux.so.2 => not found

可以看出libc.so.6库文件需要ld-linux.so.2这个动态链接库(not found 说明在当前系统中未找到相应的库,因为系统是i386而需要的是ARM格式,所以找不到)。

这样通过arm-linux-ldd命令就可以确定各个程序所需的动态链接库,然后根据需要放到lib/目录里,就组成目标根文件系统的动态链接库集合了。

l 若选择了BusyBox的init模块,则需要配置BusyBox的初始化文件。因为Linux系统加载根文件系统后需要执行一些配置以初始化整个Linux的工作环境及init程序和Shell等。这个文件就是etc/inittab。关于此文件的详细内容可以查看man inittab。但是BusyBox的inittab格式与一般Linux下的inittab的格式是不同,所以直接拷贝PC机上/etc/inittab文件到BusyBox制作的根文件系统中是不能用的,那怎么办呢?

BusyBox自带了符合它的格式的inittab样本文件,放在examples目录下,主要内容包括:

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

::askfirst:-/bin/sh

tty2::askfirst:-bin/sh

tty3::askfirst:-bin/sh

tty4::askfirst:-bin/sh

#Stuff to do when restarting the init process

::restart:/sbin/reboot

#Stuff to do before rebooting

::ctrlaltdel:/sbin/reboot

::shutdown:/bin/umount -a -r

::shutdown:/sbin/swapoff –a

BusyBox的inittab的每一行格式如下:

<id>:<runlevels>:<action>:<process>

总共包含四项,每项间以”:”隔开。

第一二项<id>和<runlevels>在BusyBox都是忽略掉的,所以可以看到BusyBox提供的inittab样本文件的所有项目都是以两个冒号”::”开头的。

第三项<action>为动作描述,可选项为sysinit, respawn, askfirst, wait, once, restart, ctrlaltdel 和 shutdown。其中大部分动作可以通过动作名直接理解它的作用。其中askfirst会在登录shell前提示用户,而respawn则不会提示。

第四项<process>指定了<action>动作应执行的脚本文件。

知道了格式,下面简单的分析一下inittab样本文件:

第一行::sysinit:/etc/init/rcS实际上指定了系统初始化(sysinit)时脚本为/etc/init/rcS,这个可以根据自己的需要更改的。

但是对于不同的终端设备的不同配置区别在于开头的标志,例如对于tty2终端,则有对应的操作 tty2::askfirst:-bin/sh。此行的意思指对于tty2使用shell为/bin/sh,同时对askfirst(有提示信息再要求登陆)。 若对于某个特定的终端设备可以直接将前面的设备标志去掉,例如ttyS0, ttyS1等。

第二行::askfirst:-/bin/sh指定了系统第一个终端在加载shell为/bin/sh,而且在进入shell前会提示用户。其它行请读者自行分析。

l 在etc/目录里除了inittab文件外,还需要其它的一些基本的文件,例如fstab、passwd、group、inputrc等,由于篇幅所限,不可能一一详解,读者可以参考其它书籍或者man手册,对于一些文件读者也可借用别的嵌入式根文件系统里的内容,然后在此基础上进行修改以符合自己的系统。这里简单介绍etc/里的几个文件:

ü fstab:这个文件描述系统中各种文件系统的信息。在这个文件中,每个文件系统用一行来描述,在每一行中,用空格或TAB符号来分隔各个字段,文件中以*开头的行是注释信息。一般内容可能如下:

/dev/mtdblock2 / jffs2 defaults 0 0

none /tmp ramfs defaults 0 0

none /proc proc defaults 0 0

第一列(字段):设备名或者设备卷标名(一般为/dev里的对应的设备文件)

第二列(字段):设备挂载目录 (例如上面的“/”或者“/tmp”)

第三列(字段):设备文件系统 (例如上面的“ext3”或者“vfat”)

第四列(字段):挂载参数 (具体可以查看帮助man mount)

对于已经挂载好的设备,例如上面的/dev/sda2,现在要改变挂载参数,这时可以不用卸载该设备,而可以使用下面的命令(没有挂载的设备,remount 这个参数无效)

#mount /mnt -o remount,ro (改defaults为ro)

关于其它参数请参考man手册。

第五列(字段):指明是否要备份。(0为不备份,1为要备份)

第六列(字段):指明自检顺序。 (0为不自检,1或者2为要自检,如果是根分区要设为1,其他分区只能是2)

ü passwd和group保存着Linux系统的用户组和用户名等,与硬件平台无关,为方便起见,可以从现有的Linux系统中拷贝过去即可。

etc/目录里的配置文件较多,不可能一一解释,请读者在创建时多参考已有的系统。

5、总结

上面已经介绍一个根文件系统的创建过程,如果完整的按照上面的步骤做下来,应该就会在/rootfs下得到了一个相对完整的根文件系统,这个根文件系统主要BusyBox的bin/、sbin/目录,etc/系统配置文件目录以及lib/动态链接库所在目录等,这样一个Linux应用程序可执行的最小环境基本已经搭成了。之后可以在这个根文件系统中添加所需的应用程序等等。

但是这个根文件系统又是怎么放到目标开发板里的呢?

通常的做法是将整个根文件系统打包成某种文件系统格式的映像,然后下载到目标开发板的存储设备里(如FLASH等)。

用什么程序可以打包?支持几种格式呢?

通常使用mkfs系统命令。mkfs命令可以生成指定文件系统类型的映像文件。对于不同的文件系统类型需要不同的mkfs命令,例如EXT2,EXT3类型的文件可以使用mkfs.ext2和mkfs.ext3等。而通常嵌入式开发板使用FLASH作为存储设备,所以对应的文件系统类型一般为JFFS2,所以使用命令mkfs.jffs2命令,这个命令一般在开发板提供的工具有,也可以从网上搜索下载,这个命令一般是运行在PC系统上的,所以一般为I386可执行文件。

mkfs.jffs2的基本命令格式如下:

mkfs.jffs2 -r DIR -o FILE -e SIZE --pad=PADSIZE

其中DIR为要打包的文件夹,FILE为输出的文件路径,SIZE为每次擦除的块大小(默认为64KB)。PADSIZE为填充大小,这个参数强制使目标文件大小至少为PADSIZE字节,若实际数据没有这么大,则使用0xFF填充,这个参数很重要,在将映像写入目标开发板时一般应与实际根文件系统大小相符(类似于总磁盘容量),这样具有初始化的作用,若不相符合,在挂载这个JFFS2根文件系统时可能会出现一些问题。

下面给个简单的例子,这个例子将/rootfs的这个根文件系统打包成文件rootfs.img,且总大小为1M(0x100000字节)。

mkfs.jffs2 -r /rootfs -o rootfs.img -e 0x40000 --pad=0x100000

做好映像文件后就可以将这个映像文件写入目标板中,通常使用U-BOOT等BootLoader通过网卡下载到开发板内存中,然后再写入开发板的FLASH里。在U-BOOT里若网卡驱动可用,通常用tftp下载,再使用相关的FLASH操作命令写数据。


你可能感兴趣的:(使用busybox制作rootfs)