根文件系统构建
BusyBox 下载
BusyBox 可以在其官网下载到,官网地址为: https://busybox.net/, 官网比较简陋,如图

在官网左侧的“Get BusyBox”栏有一行“Download Source”,点击“Download Source”即可打开 BusyBox 的下载页,使用的版本是 1.29.0 版本的 BusyBox
编译 BusyBox 构建根文件系统
1、修改 Makefile,添加编译器
打开 busybox 的顶层 Makefile,添加 ARCH 和 CROSS_COMPILE的值
为自己编译器的参数,如图:

2、配置 busybox
进入menuconfig配置一下几点:
选项“Build static binary (no shared libs)”用来决定是静态编译 busybox 还是动态编译,静
态编译的话就不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库
文件,但是编译出来的 busybox 会小很多。这里我们不能采用静态编译!因为采用静态编译的
话 DNS 会出问题!无法进行域名解析,配置如图

默认会选中“Simplified modutils”,这里我们要取消勾选!!

确保下面的全部选中,默认都是选中的

最后就是使能 busybox 的 unicode 编码以支持中文,配置路径如下:

3.编译 busybox
配置好 busybox 以后就可以编译了,我们可以指定编译结果的存放目录,我们肯定要将编
译结果存放到前面创建的 rootfs 目录中,输入如下命令:
make
make install CONFIG_PREFIX=/home/qq/linux/nfs/rootfs
编译完成以后会在 busybox 的所有工具和文件就会被安装到 rootfs 目录中, rootfs 目录内容
如图 :

rootfs 目录下有 bin、 sbin 和 usr 这三个目录,以及 linuxrc 这个文件。前面说过 Linux 内核 init 进程最后会查找用户空间的 init 程序,找到以后就会运行这个用
户空间的 init 程序,从而切换到用户态。如果 bootargs 设置 init=/linuxrc,那么 linuxrc 就是可以作为用户空间的 init 程序,所以用户态空间的 init 程序是 busybox 来生成的
向根文件系统添加 lib 库
Linux 中的应用程序一般都是需要动态库的,当然你也可以编译成静态的,但是静态的可执行
文件会很大。如果编译为动态的话就需要动态库,所以我们需要先根文件系统中添加动态库。
在 rootfs 中创建一个名为“lib”的文件夹 。lib 库文件从交叉编译器中获取, 我搭建
交叉编译环境的时候将交叉编译器存放到了“/usr/local/arm/”目录中。交叉编译器里面有很多
的库文件,这些库文件具体是做什么的我们作为初学者肯定不知道,就简单粗暴的把所有的库文件都放到我们的根文件系统中
文件路径为:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linuxgnueabihf/libc/lib
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
此目录下有很多的*so*(*是通配符)和.a 文件,这些就是库文件,将此目录下所有的*so*和.a
文件都拷贝到 rootfs/lib 目录中
。注意拷贝的库文件中是否有软链接 如果有的话就删除软链接并拷贝相应的链接文件
。
向 rootfs 的“usr/lib”目录添加库文件
在 rootfs 的 usr 目录下创建一个名为 lib 的目录,将如下目录中的库文件拷贝到 rootfs/usr/lib
目录下:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/
usr/lib
至此,根文件系统的库文件就全部添加好了,
创建其他文件夹
在根文件系统中创建其他文件夹,如 dev、 proc、 mnt、 sys、 tmp 和 root 等,
根文件系统初步测试
接下来我们使用测试一下前面创建好的根文件系统 rootfs,测试方法就是使用 NFS 挂载, uboot 里面的 bootargs 环境变量会设置“root”的值,所以我们将 root 的值改为 NFS 挂载即可。
在 Linux 内核源码里面有相应的文档讲解如何设置,文档为 Documentation/filesystems/nfs/
nfsroot.txt,格式如下:
root=/dev/nfs nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>] ip=<client-ip>:<server-ip>:<gwip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>
根据上面的格式 bootargs 环境变量的 root 值如下:
root=/dev/nfs nfsroot=192.168.1.250:/home/qq/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.251:192.168.1.250:192.168.1.1:255.255.255.0::eth0:off
进入 uboot 命令行模式,然后重新设置 bootargs 环境变量,命令如下:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.250: /home/qq/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.251:192.168.1.250:192.168.1.1: 255.255.255.0::eth0:off' //设置 bootargs
设置好以后使用“boot”命令启动 Linux 内核,结果如图所示:

进入根文件系统的时候会有下面这一行错误提示: can't run '/etc/init.d/rcS': No such file or directory
提示很简单,说是无法运行“/etc/init.d/rcS”这个文件,因为这个文件不存在。
创建/etc/init.d/rcS 文件
rcS 是个 shell 脚本, Linux 内核启动以后需要启动一些服务,而 rcS 就是规定启动哪些文件
的脚本文件。在 rootfs 中创建/etc/init.d/rcS 文件,然后在 rcS 中输入如下所示内容:
#!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib export PATH LD_LIBRARY_PATH mount -a mkdir /dev/pts mount -t devpts devpts /dev/pts echo /sbin/mdev > /proc/sys/kernel/hotplug mdev -s
第 1 行,表示这是一个 shell 脚本。
第 3 行, PATH 环境变量保存着可执行文件可能存在的目录,这样我们在执行一些命令或
者可执行文件的时候就不会提示找不到文件这样的错误。
第 4 行, LD_LIBRARY_PATH 环境变量保存着库文件所在的目录。
第 5 行,使用 export 来导出上面这些环境变量,相当于声明一些“全局变量”。
第 7 行,使用 mount 命令来挂载所有的文件系统,这些文件系统由文件/etc/fstab 来指定,
所以我们一会还要创建/etc/fstab 文件。
第 8 和 9 行,创建目录/dev/pts,然后将 devpts 挂载到/dev/pts 目录中。
第 11 和 12 行,使用 mdev 来管理热插拔设备,通过这两行, Linux 内核就可以在/dev 目录
下自动创建设备节点。关于 mdev 的详细内容可以参考 busybox 中的 docs/mdev.txt 文档。
创建好文件/etc/init.d/rcS 以后一定要给其可执行权限!
设置好以后就重新启动 Linux 内核,启动以后如图所示:

从图可以看到,提示找不到/etc/fstab 文件,还有一些其他的错误,我们先把/etc/fstab
这个错误解决了。说不定把这个问题解决以后其他的错误也就解决了。前面我们说了“mount -
a”挂载所有根文件系统的时候需要读取/etc/fstab,因为/etc/fstab 里面定义了该挂载哪些文件,
好了,接下来就是创建/etc/fstab 文件。
创建/etc/fstab 文件
在 rootfs 中创建/etc/fstab 文件, fstab 在 Linux 开机以后自动配置哪些需要自动挂载的分区,
格式如下:
<file system> <mount point> <type> <options> <dump> <pass>
<file system>:要挂载的特殊的设备,也可以是块设备,比如/dev/sda 等等。
<mount point>:挂载点。
<type>:文件系统类型,比如 ext2、 ext3、 proc、 romfs、 tmpfs 等等。
<options>:挂载选项,在 Ubuntu 中输入“man mount”命令可以查看具体的选项。一般使
用 defaults,也就是默认选项, defaults 包含了 rw、 suid、 dev、 exec、 auto、 nouser 和 async。
<dump>:为 1 的话表示允许备份,为 0 不备份,一般不备份,因此设置为 0。
<pass>:磁盘检查设置,为 0 表示不检查。根目录‘/’设置为 1,其他的都不能设置为 1,
其他的分区从 2 开始。一般不在 fstab 中挂载根目录,因此这里一般设置为 0。
按照上述格式,在 fstab 文件中输入如下内容:
#<file system> <mount point> <type> <options> <dump> <pass> proc /proc proc defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 sysfs /sys sysfs defaults 0 0
fstab 文件创建完成以后重新启动 Linux,结果如图 所示:

从图 可以看出,启动成功,而且没有任何错误提示。但是我们要还需要创建一个
文件/etc/inittab。
创建/etc/inittab 文件
inittab 的详细内容可以参考 busybox 下的文件 examples/inittab。 init 程序会读取/etc/inittab
这个文件, inittab 由若干条指令组成。每条指令的结构都是一样的,由以“:”分隔的 4 个段组
成,格式如下:
<id>:<runlevels>:<action>:<process>
<id>:每个指令的标识符,不能重复。但是对于 busybox 的 init 来说, <id>有着特殊意义。
对于 busybox 而言<id>用来指定启动进程的控制 tty,一般我们将串口或者 LCD 屏幕设置为控
制 tty。
<runlevels>: 对 busybox 来说此项完全没用,所以空着。
<action>:动作,用于指定<process>可能用到的动作。 busybox 支持的动作如表 38.4.3.1 所
示:

<process>: 具体的动作,比如程序、脚本或命令等。
参考 busybox 的 examples/inittab 文件,我们也创建一个/etc/inittab,在里面输入如下内容:
1 #etc/inittab 2 ::sysinit:/etc/init.d/rcS 3 console::askfirst:-/bin/sh 4 ::restart:/sbin/init 5 ::ctrlaltdel:/sbin/reboot 6 ::shutdown:/bin/umount -a -r 7 ::shutdown:/sbin/swapoff -a
第 2 行,系统启动以后运行/etc/init.d/rcS 这个脚本文件。
第 3 行,将 console 作为控制台终端,也就是 ttymxc0。
第 4 行,重启的话运行/sbin/init。
第 5 行,按下 ctrl+alt+del 组合键的话就运行/sbin/reboot,看来 ctrl+alt+del 组合键用于重
启系统。
第 6 行,关机的时候执行/bin/umount,也就是卸载各个文件系统。
第 7 行,关机的时候执行/sbin/swapoff,也就是关闭交换分区。
/etc/initta 文件创建好以后就可以重启开发板即可,至此!根文件系统要创建的文件就已经
全部完成了。接下来就要对根文件系统进行其他的测试,比如是我们自己编写的软件运行收费
正常、是否支持软件开机自启动、中文支持是否正常以及能不能链接等。
根文件系统其他功能测试
在 ubuntu 下使用 vim 编辑器新建一个 hello.c 文件 。使用 arm-linux-gnueabihf-gcc 将 hello.c 编译为 hello 可执行文件
将其拷贝到 rootfs/drivers 目录下 。在开发板上执行这个软件。

ok 现在为止最基本的文件系统构建完成,其他的linux版本的文件系统都是类似只是增加了不同的软件软件而已。
浙公网安备 33010602011771号