使用Busybox构建根文件系统
**环境:**Ubuntu 20.04
野火imx6ull pro开发板
根文件系统里都有什么内容
在构建根文件系统之前,先来看一下根文件系统里面大概都有些什么内容,以Ubuntu为例,根文件系统的目录名字为/
,可以直接cd
进去,进入后输入ls
命令查看根目录下的内容,结果如图所示:
接下来看一下常用的子目录。
/bin目录
看到“bin”应该能想到bin文件,bin文件就是可执行文件。所以此目录下存放着系统需要的可执行文件,一般都是一些命令,比如ls、mv等命令。此目录下的命令所有的客户都可以使用。/dev目录
dev是device的缩写,所以此目录下的文件都是和设备有关的,此目录下的文件都是设备文件。在Linux下一切皆文件,即使是硬件设备,也是以文件的形式存在的。/etc目录
此目录下存放着各种配置文件,可以进入Ubuntu的/etc目录看一下,里面的配置文件非常多!但是在嵌入式Linux下此目录会很简洁。/lib目录
lib是library的简称,也就是库的意思,此目录下存放着Linux所必须的库文件。这些库文件是共享库,命令和用户编写的应用程序要使用这些库文件。/mnt目录
临时挂载目录,一般是空目录,可以在此目录下创建空的子目录,比如/mnt/sd、/mnt/usb这样就可以将SD卡或者U盘挂载到/mnt/sd或者/mnt/usb目录中。/proc目录
此目录一般是空的,当Linux系统启动以后会将此目录作为proc文件系统的挂载点,proc是个虚拟文件系统,没有实际的存储设备。proc里面的文件都是临时存在的, 一般用来存储系统运行信息文件。/usr目录
要注意,usr是Unix Software Resource的缩写,也就是Unix操作系统软件资源目录。Linux一般被成为类Unix操作系统,苹果的MacOS也是类Unix操作系统。既然是软件资源目录,因此/usr目录下也存放着很多软件,一般系统安装完成以后此目录占用的空间最多。/var目录
此目录存放一些可以改变的数据。/sbin目录
此目录也用于存放一些可执行文件,但是此目录下的文件或者说命令只有管理员才能使用,主要用户系统管理。/sys目录
系统启动以后此目录作为sysfs文件系统的挂载点,sysfs是一个类似于proc文件系统的特殊文件系统,sysfs也是基于ram的文件系统,也就是说它也没有实际的存储设备。此目录是系统设备管理的重要目录,此目录通过一定的组织结构向用户提供详细的内核数据结构信息。/opt
可选的文件、软件存放区,由用户选择将哪些文件或软件放到此目录中。
构建根文件系统就是研究如何创建上面这些目录以及子目录中的文件。
BusyBox简介
由前面了解到,根文件系统里面就是一堆的可执行文件和其他文件组成的,那么其实需要一种工具,负责“收集”这些文件,然后将其打包,给开发者可以直接拿来用。BusyBox就是实现了这样的功能。 BusyBox是一个集成了大量的Linux命令和工具的软件,像ls、mv、ifconfig等命令BusyBox都会提供。 BusyBox就是一个大的工具箱,这个工具箱里面集成了Linux的许多工具和命令。
Busybox的下载
BusyBox可以在其官网下载到,官网地址:https://busybox.net/BusuBox
进入官网,在官网左侧的Get BusyBox
栏有一行Download Source
,点击Download Source
即可打开BusyBox的下载页,如下图所示:
根据自己来选择合适的版本,这里我选择下载busybox-1.32.0.tar.bz2
这个压缩包即可,BusyBox准备好以后就可以构建根文件系统了。
编译BusyBox
一般在Linux驱动开发的时候都是通过nfs
服务挂载根文件系统的,当产品最终上市开卖的时候才会将根文件系统烧写到EMMC或者NAND中。所以要在 之前设置的nfs服务器目录中创建一个名为rootfs的子目录使用如下命令创建名为rootfs的子目录:
cd ~
在~
目录下创建busybox_dir
文件夹,准备放Busybox的源码
mkdir busybox_dir
将busybox-1.32.0.tar.bz2
放到busybox_dir
。然后使用如下命令将其解压:
tar -vxjf busybox-1.32.0.tar.bz2
解压后如图所示:
修改busybox配置文件支持中文
打开文件busybox-1.32.0/libbb/printable_string.c
,找到函数printable_string2
,缩减后的函数内容如下:
待修改处1:
修改后如下图所示:
待修改处2:找到下图位置
修改后如下图所示:
接着打开文件busybox-1.32.0/libbb/unicode.c
待修改处1:找到下图位置
修改后如下图所示:
待修改处2:找到下图位置
修改后如下图所示:
使用图形化界面配置busybox
修改makefile文件,有两处要修改:
1:修改为交叉编译器,根据自己情况来,在164行
2:修改平台为arm,在193行
配置busybox
和之前编译Uboot、Linux kernel一样,要先对busybox进行默认的配置,有以下几种配置选项:
defconfig 缺省配置,也就是默认配置选项。
allyesconfig 全选配置,也就是选中busybox的所有功能。
allnoconfig 最小配置
defconfig 默认配置
输入如下命令,使用默认配置defconfig
文件来配置一下busybox:
sudo make defconfig
执行上述命令配置成功后会生成.config
文件
busybox也支持图形化配置,通过图形化配置可以进一步选择自己想要的功能,输入如下命令打开图形化配置界面:
make menuconfig
sudo make ARCH=arm CROSS_COMPILE=/home/cwz/toolchain/gcc-linaro-4.9-2015.05-1-rc1-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi- menuconfig
打开后如下图所示:
配置1
配置路径如下:
Location:
-> Settings-> Build static binary (no shared libs)
选项“Build static binary (no shared libs)”用来决定是静态编译是动态编译,静态编译的话就不需要库文件,但是编译出来的根文件系统会很大。动态编译要求根文件系统中有库文件,但是编译出来的 busybox会小很多。这不能采用静态编译!因为采用静态编译的话DNS会出问题!无法进行域名解析,配置如下图所示:
配置2
配置路径如下:
Location:
-> Settings-> vi-style line editing commands
结果如下图所示:
配置3
配置路径如下:
Location:
-> Linux Module Utilities-> Simplified modutils
结果如下图所示:
配置4
配置路径如下:
Location:
-> Linux System Utilities-> mdev (17 kb)
确保全部选中,默认都是选中的如下图所示:
配置5
使能busybox的unicode编码以支持中文
配置路径如下:
Location:
-> Settings-> Support Unicode -> Check $LC_ALL, $LC_CTYPE and $LANG environment variables
选中结果如下图所示:
保存配置文件
使用图形化修改过Busybox的配置以后最好保存一下配置文件,后期可以直接加载这个配置文件,也可以避免make clean
删除掉以前的配置,在配置主界面上,如下图所示:
进入后,命名要生成的文件。
将会在本目录下生成config_busybox
文件
编译文件
CONFIG_PREFIX
变量指定将编译好的文件放到/home/workdir/rootfs
目录下(这里也是我自己设置的NFS服务的共享目录,根据自己的设置)。输入如下命令:
sudo make install CONFIG_PREFIX=/home/workdir/rootfs
输入上述命令,编译完成以后如下图所示:
编译生成的文件在/home/workdir/rootfs
如下图:
可以看到,/home/workdir/rootfs
目录下有bin
、sbin
和usr
这三个目录,以及linuxrc
这个文件。前面说过Linux内核init进程最后会查找用户空间的 init程序
,找到以后就会运行这个用户空间的init程序
,从而切换到用户态。如果bootargs设置init=/linuxrc
,那么linuxrc就是可以作为用户空间的 init
程序,所以用户态空间的init程序
是busybox
来生成的。
添加库文件
busybox的工作就完成了,但是此时的根文件系统还不能使用,还需要一些其他的文件,还需要继续完善rootfs。
向根文件系统添加lib库
向rootfs的/lib
目录添加库文件
Linux中的应用程序一般都是需要动态库的,当然也可以编译成静态的,但是静态的可执行文件会很大。如果编译为动态的话就需要动态库,所以需要向根文件系统中添加动态库。在/home/workdir/rootfs
中创建一个名为lib
的文件夹,命令如下:
mkdir lib
lib文件夹
创建好了,库文件从哪里来呢?lib库文件
从交叉编译器中获取,这里我所使用到的交叉编译器是gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf
。交叉编译器里面有很多的库文件,可以直接把所有的库文件都放到根文件系统中。进入如下路径(下面的路径根据自己的交叉编译器来设置)对应的目录:
进入到库所在的目录
cd /home/cwz/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
此目录下有很多的*so*
(*是通配符)文件,这些就是库文件。
将此目录下所有的*so*
文件都拷贝到/home/workdir/rootfs/lib
目录中,进入到库所在的目录使用下面命令将库文件拷贝:
cp *so* *.a /home/workdir/rootfs/lib/ -d
后面的-d
表示拷贝符号链接。
这里有个比较特殊的库文件ld-linux-armhf.so.3
,此库文件也是个符号链接,相当于Windows下的快捷方式。会链接到库ld-2.25.so
上,输入命令下面命:
ls ld-linux-armhf.so.3 -l
但是ld-linux-armhf.so.3
不能作为符号链接,否则的话在根文件系统中执行程序无法执行!所以需要将ld-linux-armhf.so.3
的实体拷贝过去,方法很简单,那就是重新复制ld-linux-armhf.so.3
,只是不复制软链接即可,先将/home/workdir/rootfs/lib/
中的ld-linux-armhf.so.3
文件删除掉,命令如下:
rm ld-linux-armhf.so.3
然后重新进入到/home/cwz/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
目录中
cd /home/cwz/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
重新拷贝ld-linux-armhf.so.3
,命令如下:
cp ld-linux-armhf.so.3 /home/workdir/rootfs/lib/
拷贝完成以后再到/home/workdir/rootfs/lib/
目录下查看ld-linux-armhf.so.3
文件详细信息,如下图所示:
从上图可以看出,此时ld-linux-armhf.so.3
已经不是软连接了,而是实实在在的一个库文件。
继续进入如下目录中:
cd /home/cwz/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
此目录下也有很多的的*so*
和.a
库文件,将其也拷贝到/home/workdir/rootfs/lib/
目录中,命令如下:
cp *so* *.a /home/workdir/rootfs/lib/ -d
目录的库文件就拷贝完成了。
在/home/workdir/rootfs/usr
目录下创建一个名为lib
的目录
进入到/home/cwz/toolchain/gcc-linaro-4.9-2015.05-1-rc1-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/libc/usr/lib
目录中,
cd /home/cwz/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib
将此目录下的库文件拷贝到/home/workdir/rootfs/usr/lib
目录下下。
cp *so* *.a /home/workdir/rootfs/usr/lib/ -d
至此,根文件系统的库文件就全部添加好了。
创建其他文件夹
在根文件系统中创建其他文件夹,如dev、proc、mnt、sys、tmp、etc和root等,
mkdir dev proc mnt sys tmp etc root
创建完成以后如下图所示:
目前看起来已经完成了,接下来就可以测试一下根文件系统了。
参考:
-1700623668096)]
目前看起来已经完成了,接下来就可以测试一下根文件系统了。