本文介绍如何利用busybox制作一个最小根文件系统,系统包含ls、cd、ifconfig等基本指令,文件系统采用动态加载的方式。
1.去busybox官网下载源码
- 官网地址:busybox官网
- 下载busybox-1.29.0版本。
2.将源码拷贝至Linux主机并解压
将busybox源码拷贝到linux主机并解压,同时新建一个rootfs文件夹,用于保存待会制作好的根文件系统。
3.配置makefile
进入busybox源码主目录,首先配置makefile文件:
- cd busybox-1.29.0
- vim makefile
makefile需要改的就是指定处理器架构和交叉编译器。
4.配置busybox
- make menuconfig
首先是setting
接下来是Linux Module Utilities配置
接下来是 Linux System Utilities配置
write support 下面的6个子选项需要全部勾上。
最后是shell配置:bash shell和sh 最终都解释为ash运行
以上配置完成以后,保存退出。
5.编译busybox
- make
在源码根目录下执行make编译:
出现了错误,提示setns和syncfs未定义,出现这两个错误的原因就不分析了,由于这两个文件对于根文件系统的影响微乎其微,所以我们在menuconfig里把这两个地方屏蔽掉就可以了。
然后保存退出,继续编译。
6.安装文件系统
- make install CONFIG_PREFIX=/test/rootfs/
CONFIG_PREFIX是指定文件系统安装位置,这里指向我们刚刚新建的rootfs文件夹
安装完成,我们去rootfs文件夹看下:
多了这4个文件(夹),至此busybox的任务就完成了。但是这个根文件系统是不完整的,还缺少很多东西,所以接下来我们就需要完善这个根文件系统。
7.构建lib目录
由于我们在menuconfig里选择的是动态库,所以我们需要构建需要的动态库文件(.so文件)。
这些动态库文件在交叉编译器的目录下可以找到,我们直接把整个lib复制过来。
- mkdir lib
- cp /ZLG_linux/gcc-4.4.4-glibc-2.11.1-multilib-1.0/arm-fsl-linux-gnueabi/arm-fsl-linux-gnueabi/multi-libs/lib/* /test/rootfs/lib/ -a
注意复制的时候要选择-a,因为lib下有很多链接文件,我们需要将链接文件和链接文件的源文件都复制过来。
由于我的lib库里自带了很多静态库文件,这些静态库文件是不需要的而且占用很大空间,所以需要将它们删除:
- rm -f *.a
我们可以看下lib文件的大小:
有7.6M,这个lib文件还是比较大的,因为里面有很多用不到的库,我们也一并复制过来了,但是影响不大。
注意:也可以在lib下使用arm-fsl-linux-gnueabi-strip *去掉lib里面库文件的符号文件 对库文件进行瘦身(去除符号表和调试信息)
至此,lib文件就构建完成了。
8.构建etc目录
我们可以把/busybox-1.29.0/examples/bootfloppy下的etc目录直接拷贝过来。
在配置etc目录之前首先简单讲下文件系统的启动顺序:
- Linux内核启动过程中,运行的第一个程序是init程序,通常是根目录下的linuxrc,而这是一个指向/bin/busybox 的链接,也就是说,系统起来后运行的第一个程序就是busybox本身。
- linuxrc 会解析/etc/inittab内容,运行相关子进程,首先会运行etc/inittab配置文件里面/etc/init.d/rcS这个脚本!
- rcS脚本中会运行mount -a命令,这条命令会读取/etc/fstab 内容进行挂载各个文件系统,然后执行创建/dev文件的脚本。
- 系统起来后,登陆用户后会运行/etc/profile,进行相关环境变量的配置;
刚刚拷贝过来的etc文件夹已经包含了上述的几个必要文件,但是还需要做一些修改:
inittab:配置文件,里面包含需要执行的脚本,第一个需要执行的脚本就是/etc/init.d/rcS
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
rcS:脚本程序
首先设置网卡MAC地址和IP地址(也可以放到profile里面),mount -a命令会挂载各个虚拟文件系统,mdev是udev的嵌入式简化版本,udev/mdev是用来配合linux驱动工作的一个应用层的软件,udev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件,echo /sbin/mdev > /proc/sys/kernel/hotplug为设置内核热插拔,当有设备的热插拔时调用/sbin/mdev。最后一条命令指定了一个主机名配置文件(这个文件一般文件名叫hostname或者HOSTNAME).
#! /bin/sh
ifconfig eth0 hw ether 02:00:92:B3:C4:08
ifconfig eth0 192.168.0.100
/bin/mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
/bin/hostname -F /etc/sysconfig/HOSTNAME
fstab:配置文件,在Linux开机以后自动配置哪些需要自动挂载的分区,mount -a指令会读取本文件的内容,然后挂载虚拟文件系统。格式如下:
file system | mount point | type | options | dump | pass |
要挂载的特殊的设备 |
挂载点 | 文件系统类型,比如 ext2、ext3、proc、romfs、tmpfs 等等。 | 挂载选项,一般为default | 为 1 的话表示允许备份,为 0 不备份,一般不备份,因此设置为 0 | 磁盘检查设置,为 0 表示不检查 |
#
# /etc/fstab: static file system information.
#
# file system mount type options dump pass
#/dev/root / ext2 rw,noauto 0 1
proc /proc proc defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
usbfs /proc/bus/usb usbfs defaults 0 0
/dev/fd0 /mnt/floppy auto noauto,owner 0 0
/dev/cdrom /mnt/cdrom iso9660 noauto,owner,ro 0 0
profile:PS1是主提示符变量,也是默认提示符变量。默认值[\u@\h \W]\$
,显示用户主机名称工作目录。
# /etc/profile: system-wide .profile file for the Bourne shells
export PS1='[\u@\h \W]\# '
接着在etc下创建目录sysconfig, 然后再sysconfig目录下创建HOSTNAME文件,往这个文件中写入你想要设置的主机名。
这里暂设主机名为busybox。
实际上,到这里根文件系统的主要目录和文件已经构建完成,这时候的根文件系统已经可以运行!
9.构建其他目录
为了方便使用,我们再创建几个其他常用目录
- mkdir mnt tmp dev proc sys root
一个最小版根文件系统制作完成!下面就可以利用NFS或者写入FLASH测试这个文件系统了。
10.添加root用户
最后,给中这个文件系统添加一个root用户,无密码。
在/etc添加passwd文件,内容如下:
root::0:0:root:/root:/bin/sh
11.测试
我是直接将文件系统烧到板子的NAND FLASH里面去测试的。
可以看到,文件系统已经成功启动!接下来,写个hello world 看下动态库加载是否正常。
程序成功运行,动态库加载也没有什么问题!