静下来,定好方向,好好干。
分类: LINUX
2008-01-30 12:22:16
利用BusyBox做一个简单的根文件系统
1、下载BusyBox源代码包
2、找个地方解压缩包,例如tar -xjvf busybox-1.00.tar.bz2
3、进入busybox的文件夹,使用make menuconfig进入设置
[attach]244[/attach]
4、在build options中有一些选项要注意
Build BusyBox as a static binary (no shared libs):如果选择了这个选项,那么BusyBox将被静态编译,也就是不需要动态链接库的支持就能运行,但是这样会使编译后文件的体积增大。
Do you want to build BusyBox with a Cross Compiler:如果你的busybox将要运行机器与编译主机的体系结构不同,比如s3c2410是ARM,与我们的X86主机芯片系统结构不一样,那么这个一定要选上,并且在 Cross Compiler prefix中写上交叉编译器的名字,比如ARM用arm-linux-
[attach]245[/attach]
5、在Installation Options中 BusyBox installation prefix就是在编译完后运行make install 时,busybox将被安装的地址。
[attach]246[/attach]
6、其它的选项按照默认选项就行,当然自己也可以看看有没有需要,把其它一些命令加入到编译选项中来
7、完成后保存,然后运行make
8、编译没有问题后运行make install这样编译好的busybox就会自动安装到BusyBox installation prefix中,一般是三个文件夹bin sbin usr和一个文件linuxrc。这样busybox的编译就完成了
9、准备一个空文件夹将BusyBox installation prefix中的东西拷过来,另外再建几个linux需要的文件夹
lib
dev
etc
home
proc
root
tmp
var
mnt
10、在etc文件夹下建一个目录init.d,并且在其中建立一个空文件rcS,在rcS中加上以下内容
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
#
# Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP
/bin/mount -t proc none /proc
11、如果你的busybox是静态编译的,那么一个简单的能使用的根文件系统就这样完成了,但是这个文件系统中没有glibc的动态链接库,除了busybox以外的软件,如果对glibc有依赖,但是又没有静态编译的的话就无法运行。但如果所有的软件都用静态编译的话,那这个文件系统将很大。所以一般推荐软件不要使用静态编译,而使用一个库。
12、如果你不是用静态编译的,那么你需要编译好的glibc的动态链接库。在一般的交叉编译器中都带有已经编译好的库,直接拷过来就行了。一般在交叉编译器的lib或arm-linux/lib中
2编译busybox
2004年10月中旬,busybox的1.00稳定版终于推出了,完整的源代码可以从下载,压缩包大小为1.3 MB左右。将源码解压之后,进入到busybox1.00目录中,运行make menuconfig可以打开它的编译界面。这个界面和Linux内核编译有些接近,如图1所示。
在这个菜单界面中除了可以对最终编译到可执行文件中的命令进行选择外,还有很多其他设置也是非常重要的。下面三个目录是很多人都会感兴趣的:
Build Options --->
Installation Options --->
Login/Password Management Utilities --->
在Build Options里面有是否使用交叉编译的选项(Do you want to build BusyBox with a Cross Compiler)。如果要对其他平台进行编译就要选择它并设置相应的编译程序前缀。
在Installation Options里面可以设置安装的路径,即设置为新文件系统的根目录。当然也可以用缺省的 _install目录,安装之后再复制到新文件系统中去。
在设置Login/Password Management Utilities的时候,为了免去配置glibc的麻烦,最好设置使用busybox自己的password和shadow文件的功能(Use internal password and group functions rather than system functions)。
busybox提供的命令无疑比较全面,但它的缺省配置还不能构成一个功能比较完备的文件系统。必须要添加的命令有Login/Password Management Utilities里面的getty、login和passwd,这些命令从前是由另外一个软件包tinylogin所提供的。当然,如果不需要一个交互的登录界面,这些命令也可以去掉。通过设定内核参数init=/bin/sh可以在系统启图1busybox的编译配置界面动后直接得到一个shell。
tlenetd命令是一个远程登录服务程序,把它编译进busybox中会为将来的调试提供很多的方便。当然也可以通过串口终端的方式管理嵌入式设备,但网络登录的方式却更为方便。
设置完毕后保存、退出,执行make; make install命令,busybox将在未来的根文件系统中建立/usr、/bin、/sbin等目录。从中可以看到,编译好的busybox可执行文件和其他应用命令的符号链接。典型的busybox文件大小在动态链接的情况下是300 KB左右,静态链接为800 KB左右,用它实现的文件系统完全可以控制在1 MB以下。但就目前为止,得到的还不是一个完整可用的文件系统,必须要在这个基础上添加一些必要的文件,让它可以工作。
3完善文件系统
3.1需要增加的文件
参考一个正常的Linux系统就会发现,busybox建立的文件系统还缺少很多文件。下面三行命令建立了常见UNIX系统中包含的一些目录,虽然它们不全是必需的,但建立它们更符合标准一些。这些命令都是在新文件系统的根目录中执行的,第三条命令的执行还必须要有root权限。
mkdir mnt root var tmp proc boot etc lib
mkdir /var/{lock,log,mail,run,spool}
chown 0:0R *
如果busybox采用了动态链接的方式编译,还需要把busybox所需要的动态库:libcrypt.so.1、libc.so.6、ldlinux.so.2放到lib目录中。最好按照标准的方式建立相应的文件和链接,可以参考下面的列表:
-rwxrwxrwx 192519ld-2.3.2.so
lrwxrwxrwx 111ld-linux.so.2 -> ld-2.3.2.so
-rwxrwxrwx 1 1190032libc-2.3.2.so
lrwxrwxrwx 113libc.so.6 -> libc-2.3.2.so
-rwxr-xr-x 118348libcrypt-2.3.2.so
lrwxrwxrwx 117libcrypt.so.1 -> libcrypt-2.3.2.so
3.2编写 etc文件夹下的文件
etc文件夹是许多系统配置文件保存的地方。这些文件非常重要,如果配置错误,就可能影响系统的启动。busybox源代码example/bootfloopy/etc目录中的文件算是一个简单的例子,可以把其中的文件拷贝过来作为基础。(在example/bootfloopy目录中的一些脚本和文档也很值得阅读)
首先inittab文件是系统启动后所访问的第一个脚本文件,后续启动的文件都由它指定。这个文件的格式和普通微机Linux上的inittab是有区别的,其具体含义可以参考busybox的文档。下面是一个比较简单的例子:
::sysinit:/etc/init.d/rcS
tty0::respawn:/sbin/getty 38400 tty0
tty2::askfirst:/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount ar
::shutdown:/bin/mount / o remount,ro
其中第一行指定了系统的启动脚本为/etc/init.d/rcS;第二行指定在第一个虚拟终端打开一个登录会话;第三行指定在第三个虚拟终端打开一个无须登录验证的shell;第四行指定了当按下ctrl+alt+del组合键时的执行命令;最后两行指定了关机时执行的操作。
fstab文件定义了文件系统的各个“挂接点”,需要与实际的系统相配合。一个简单的fstab文件如下:proc/procprocdefaults00
/dev/hda1/ext2rw,noauto01
devpts/dev/ptsdevptsdefaults00
其中第三行是为UNIX PTYs准备的,telnetd要用到。
profile文件是终端登录之后首先运行的脚本,这里可以不去管它。我们比较关心的是系统在无人登录的情况下有哪些程序要执行。从inittab文件可以看出系统启动之后要运行/etc/init.d/rcS脚本,需要启动的程序和需要进行的设置都可以写在这里面。一个可能的rcS文件如下:
#! /bin/sh
echo e 'Starting System'
ifconfig lo 127.0.0.1
ifconfig eth0 192.168.0.100
hostname F /etc/hostname
/bin/mount / o remount,rw
/bin/mount /proc
/bin/mount /dev/pts
/usr/sbin/telnetd
dmesg > /var/log/dmesg
为了满足终端登录用户验证的要求,etc目录下还需要有passwd、group和shadow (在编译busybox时如果不选择shadow功能将不需要这个文件)。这些文件至少要包含 root用户的定义,如下所示:
passwd:
root:x:0:0:root:/root:/bin/sh
group:
root:x:0:
shadow:
root::12179:0:99999:7:::
其中,如果shadow (对于不支持shadow的系统则是passwd )文件的第一个冒号和第二个冒号之间没有内容,表示这个用户登录不需要密码。如果需要设定密码或者增加新的登录用户,就可以参考开发主机上的相应文件,或者在目标系统启动之后用passwd命令和adduser命令完成。
最后还可以给目标机起一个名字,在/etc目录下建立文件hostname,将起好的名字写到里面。前面介绍的启动脚本rcS,通过hostname命令把文件的内容设置为机器名。
4测试新的文件系统
文件系统的安装随着应用环境的不同差别比较大。在嵌入式环境中,一般只要通过特殊的打包工具将文件系统打包,并烧录到非易失性存储器中就可以了。例如,对于JFFS2类型的文件系统就可以用mkfs.jffs2命令生成文件系统的映像。
文件系统安装之后重新启动目标设备,应该就可以使用新建立的文件系统了。如果系统启动失败,则可以通过内核消息查找错误的原因。如果错误信息提示不能正确挂载文件系统,问题可能出在启动引导装载程序(bootloader)上。文件系统比较容易出问题的是用户的验证和动态链接库的加载。最简单的检测办法是把busybox编译为静态链接并设置内核参数init=/bin/sh来躲开对用户登录的验证。
首先将下载的 busybox-1.1.3-tar.bz2 解压到一个目录中,然后在里面运行以下的命令,对源代码进行配置:
[root@redhat9 busybox-1.1.3]# make menuconfig
相信有过编译内核经验的人对这个界面应该很熟悉,在这个莱单里可以对 BusyBox 的编译方式进行选择,例如是静态编译还是动态编译,是使用 glibc 还是 uClibc 等;也可以选择你所需要的 applet。
如果你的操作系统是 Red Hat Linux 9.0 那么有两个问题你需要注意一下:
不要选择使用 Support NSA Security Enhanced Linux;
如果选择了 Linux Ext2 FS Progs 下的任何一个 applet,那么就必须更新你的 make,make-3.81 可以是一个选择。
完成配置后,接下来就容易了:
[root@redhat9 busybox-1.1.3]# make dep
[root@redhat9 busybox-1.1.3]# make
[root@redhat9 busybox-1.1.3]# make install
正常编译完成后,在当前源代码目录下会生成一个 _install 子目录,里面包含编译好的 busybox 和一些指向它的符号连接。
3 使用说明
调用 BusyBox 中的 applet 有三种方法(以 ls 命令为例):
给 busybox 带参数 busybox ls
硬连接 ln busybox ls
ls
符号连接 ln -s busybox ls
ls
第三种是最常用的方法,因为在 _install 目录中就已经做好了全部的符号连接。
有了 busybox 及其符号连接之后,还需要做一些附加工作才能将 BusyBox 作为操作系统使用:
基本目录:除了 _install 中已经有的 bin sbin 两个目录外,还需要建立以下目录,注意 tmp 的权限为 777,root 权限为 750
dev
dev/pts
dev/shm
etc
etc/init.d
lib
proc
tmp
var
root
设备文件:可以从你正在使用的系统中直接复制,至少需要
/dev/console
/dev/fd
/dev/fd0
/dev/fd0H1440
/dev/hd?
/dev/hd??
/dev/kmem
/dev/null
/dev/zero
/dev/tty
/dev/tty?
共享库支持:如果你的 busybox 为动态编译,则需要
/lib/libc.so.6
不论是动态编译还是静态,如果要做 DNS 解析,就一定需要
/lib/libnss_dns.so.2
/lib/libnss_files.so.2
/lib/libresolv.so.2
/etc/resolv.conf
resolv.conf 根据具体环境修改。同时,只要使用了共享库,就需要
/lib/ld-linux.so.2
/sbin/ldconfig
/etc/ld.so.conf
ld.so.conf 根据具体环境修改。注意:我这里给出的共享库文件名可能只是符号连接,一定要同时拷贝原始文件。另外,如果你使用的是 uClibc,那么请参考相应文档。
配置文件:至少需要下表文件:
/etc/protocols
/etc/services 这两文件可以直接从当前系统中复制
/etc/host 去掉不必要条目,但最少要保留“127.0.0.1 localhost”
/etc/passwd
/etc/shadow 去掉多余的用户信息,保留root和系统用户名,注意修改 shadow 之前要先给它可写权限
/etc/fstab 去掉多余的 mount 点,但至少保留以下条目:
/dev/hda1 / ext2 defaults 1 1
none /dev/pts devpts gid=5,mode=620 0 0
none /proc proc defaults 0 0
none /dev/shm tmpfs defaults 0 0
注意第一行,这里指定将 /dev/hda1 作为根目录 /,你可以根据自己的实际需求更改
/etc/mtab mount 点信息,让它为空
/etc/resolv.conf 配置 DNS 解析,这里给出一个例子:
nameserver 202.103.0.117
search localdomai
/etc/ld.so.conf 包含共享库的目录列表,可以为空
etc/inittab 不要使用标准的 inittab,因为它和 BusyBox 的 init 不兼容。在 BusyBox 源代码目录中有一个 inittab 的样本,可以在它的基础之上修改。可修改的项目有:登录方式,启动脚本 rcS 的位置,指定关机脚本等。可以不使用这个文件
etc/init.d/rcS 这是 BusyBox 系统特有的启动脚本。BusyBox 使用的 init 是没有运行级别之分的,默认情况下,它在启动之后,会先调用 /etc/init.d/rcS,然后等待登录。所以我们可以在这个脚本中做一些初始化工作。这里给出一个简单的例子,注意要给它可执行权限:
#!/bin/sh
/bin/mount /proc
/bin/mount -o remount,rw /
/bin/mount -a
ifconfig lo 127.0.0.1 broadcast 127.255.255.255 netmask 255.0.0.0
ifconfig lo up
route add -net 127.0.0.0 netmask 255.0.0.0 dev lo
etc/busybox.conf 设置 user ID,如果在编译 BusyBox 时没有选择“Support for SUID/SGID handling”,则可以不使用这个文件。在设置 busybox.conf 的同时,还要给 bin/busybox 加上“s”属性,下面是 busybox.conf 的一个例子:
# /etc/busybox.conf
[SUID]
su = sx- root.500
将上述所有的东西,包括 busybox 及其符号连接、基本目录、设备文件、配置文件以及可能需要的共享库及相关文件等等,全部按其应有的位置做到一个目录(如 _install)中备用,接下来是做成 initrd 还是微型的 Linux 启动盘,甚至是用于嵌入式系统中,就看各自的需求了。