一、根文件系统简介
cd / //进入根目录
二、BusyBox构建文件系统
1)BusyBox简介
2)编译BusyBox构建根文件系统
在nfs服务器目录中创建一个名为rootfs
的子目录,用来存放我们的根文件系统。
将busybox-1.29.0.tar.bz2
发送到Ubuntu中的合适位置(我存放在 /home/xxpcb/myTest/imx6ull/dts)并解压:
tar -vxjf busybox-1.29.0.tar.bz2
解压后的文件如下:
1 、修改Makefile添加编译器
如果坚持要修改Makefile,就是修改如下的地方,指定编译器与架构(本篇进行实验时没有修改)。
2、BusyBox中文支持
打开文件busybox-1.29.0/libbb/printable_string.c,找到函数printable_string,把某些程序注释掉,修改后的函数内容如下:
主要就是禁止字符大于0X7F以后 break 和输出‘?’
接着打开文件busybox-1.29.0/libbb/unicode.c,修改如下内容:
3、配置 busybox
有以下几种配置选项:
- defconfig:缺省配置,也就是默认配置选项
- allyesconfi:全选配置,也就是选中 busybox 的所有功能
- allnoconfig:最小配置
一般使用默认配置即可,因此使用如下命令先使用默认配置来配置一下 busybox:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig
busybox也支持图形化配置,通过图形化配置我们可以进一步选择自己想要的功能,输入如下命令打开图形化配置界面:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
- (1) 设置Settings -> Build static binary (no shared libs)
选项“Build static binary (no shared libs)”用来决定是静态编译busybox 还是动态编译,静态编译的话就不需要库文件,但是编译出来的BusyBox会很大。动态编译的话要求根文件系统中有库文件,但是编译出来的 BusyBox会小很多。这里我们不能采用静态编译,因为采用静态编译的话 DNS 会出问题!无法进行域名解析
- (2) 设置Settings -> vi-style line editing commands
这个要勾选,通过按键“y”实现勾选,使得方括号内出现星号
- (3) 配置Linux Module Utilities -> Simplified modutils
默认会选中“Simplified modutils” ,这里我们要取消勾选! 使用键盘上的“n”键取消方括号中的星号。
- (4) 配置Linux System Utilities -> mdev (16 kb)
确保下面的全部选中,默认都是选中的
- (5) 设置Settings -> Support Unicode
要将默认没有勾选的Check $LC_ALL
项选中!
最后按两下ESC退出设置,并选择YES保存。
4、 编译busybox构建根文件系统
输入如下指令进行编译:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- install CONFIG_PREFIX=/home/xxpcb/myTest/nfs/rootfs
编译完成以后, busybox的所有工具和文件就会被安装到rootfs目录中,如下图:
rootfs目录下有bin、sbin和usr三个目录,以及linuxrc文件。Linux内核linit进程最后会查找用户空间的init程序,找到以后就会运行这个用户空间的init程序,从而切换到用户态。如果bootargs设置init=/linuxrc,那么linuxrc就是可以作为用户空间的init程序。
5、根文件系统添加lib库
5.1 向rootfs/lib中添加
上面的busybox使用的是动态库编译,所以还需要向根文件系统中添加动态库。
先在rootfs中创建一个名为“lib”的文件夹。lib库文件从交叉编译器中获取,之前搭建交叉编译环境的时候将交叉编译器存放到了“/usr/local/arm/”目录中,进入对应的目录:
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
此目录下有很多的so和.a 文件,这些就是库文件,将此目录下所有的so和.a文件都拷贝到 rootfs/lib 目录中:
cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/lib/ -d
后面的“-d”表示拷贝符号链接,这里有个比较特殊的库文件:ld-linux-armhf.so.3,此库文件也是个符号链接,相当于 Windows 下的快捷方式。会链接到库 ld-2.19-2014.08-1-git.so 上,输入命令如下指令查看此文件详细信息:
ls ld-linux-armhf.so.3 -l
ld-linux-armhf.so.3 后面有个“->” ,表示其是个软连接文件,链接到文件ld-2.19-2014.08-1-git.so,因为其是一个“快捷方式” ,因此大小只有 24B。但是,ld-linux-armhf.so.3不能作为符号链接,否则的话在根文件系统中执行程序无法执行!所以我们需要重新复制ld-linux- armhf.so.3,替换掉这个软链接。
先删除这个软连接文件:
rm ld-linux-armhf.so.3
然后重新进入到 /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm- linux-gnueabihf/libc/lib 目录中,重新拷贝ld-linux-armhf.so.3,命令如下:
cp ld-linux-armhf.so.3 /home/xxpcb/myTest/nfs/rootfs/lib/
拷贝完成以后再到 rootfs/lib 目录下查看ld-linux-armhf.so.3文件详细信息,此时ld-linux-armhf.so.3 已经不是软连接了,而是实实在在的一个库文件,而且文件大小为 724392B。
继续进入如下目录中:
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
此目录下也有很多的的so和.a 库文件,我们将其也拷贝到 rootfs/lib 目录中,命令如下:
cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/lib/ -d
rootfs/lib 目录的库文件就这些了,完成以后的rootfs/lib目录如图:
5.2 向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
将此目录下的so和.a 库文件都拷贝到rootfs/usr/lib目录中:
cp *so* *.a /home/xxpcb/myTest/nfs/rootfs/usr/lib/ -d
完成以后的rootfs/usr/lib目录为:
至此,根文件系统的库文件就全部添加好了,可以在rootfs
目录下使用“du”命令来查看一下/lib和/usr/lib 这两个目录的大小:
du ./lib ./usr/lib/ -sh
6、创建其他文件夹
在根文件系统中创建其他文件夹,如 dev、proc、mnt、sys、tmp 和 root 等,创建完后的效果:
三、根文件系统初步测试
bootargs环境变量设置
使用NFS挂载的方式来测试上面创建好的根文件系统rootfs。
uboot里面的bootargs环境变量会设置root的值,需要将root的值改为NFS挂载,设置格式如为:
root=/dev/nfs nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>] ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>
<server-ip>
:服务器IP,存放根文件系统的Ubuntu的IP地址,比如我的192.168.5.105。<root-dir>
:根文件系统的存放路径,比如我的就是/home/xxpcb/myTest/nfs/rootfs。<nfs-options>
:NFS 的其他可选选项,一般不设置。<client-ip>
:客户端IP ,开发板的IP地址,Linux内核启动以后就会使用此IP地址来配置开发板。我的为92.168.5.102。<gw-ip>
:网关地址,我的就是 192.168.5.1。<netmask>
:子网掩码,我的就是 255.255.255.0。<hostname>
:客户机的名字,一般不设置,此值可以空着。<device>
:设备名,也就是网卡名,一般是 eth0,eth1….,正点原子与野火的开发板均为ENET2为eth0,ENET1为eth1。这里我们使用ENET2,所以网卡名就是 eth0。<autoconf>
:自动配置,一般不使用,所以设置为 off。<dns0-ip>
:DNS0 服务器 IP 地址,不使用。<dns1-ip>
:DNS1 服务器 IP 地址,不使用。
根据上面的格式bootargs环境变量的root值如下:
root=/dev/nfs nfsroot=192.168.5.105:/home/xxpcb/myTest/nfs/rootfs,proto=tcp rw ip=192.168.5.102:192.168.5.105:192.168.5.1:255.255.255.0::eth1:off
启动开发板,串口连接开发板,进入uboot命令行模式,然后设置bootargs环境变量,命令如下:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.5.105:/home/xxpcb/myTest/nfs/rootfs,proto=tcp rw ip=192.168.5.102:192.168.5.105:192.168.5.1:255.255.255.0::eth1:off'
saveenv
设置好以后使用“boot”命令启动Linux内核
Linux内核的启动还是按照上一篇介绍的,使用tftp将zImage和设备树传输到开发板中运行。
这里注意一下,因为此次测试,将zImage和dtb文件移入了tftp目录中的nxp文件夹中,所以传输指令需要修改一下:
setenv bootcmd 'tftp 80800000 nxp/zImage; tftp 83000000 nxp/imx6ull-myboard.dtb; bootz 80800000 - 83000000'
saveenv
然后就可以使用boot命令来进行tftp传输了。