前言:本章节讲解的是构建移植BusyBox根文件系统到linux开发板。
主要是基于正点原子Linux开发板操作。
接下来讲解具体过程记录,BusyBox源码可联系作者索取,或到官网下载:网址。
根文件系统属于Linux系统运行的最后一部分,包括uboot和Linux内核及设备树,这几部分组合有uboot开始经过Linux内核和设备树,再到根文件系统,才能真正将Linux系统运行起来,从而让开发板进入Linux系统,而后才能敲打命令行。uboot和Linux内核移植可参考下面连接。
uboot移植可参考一下:
<Linux开发> -之-系统移植 uboot移植过程详细记录(第一部分)
<Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分)
<Linux开发> -之-系统移植 uboot移植过程详细记录(第三部分)(uboot移植完结)
Linux内核及设备树移植可参考一下:
<Linux开发>系统移植 -之- linux内核移植过程详细记录(第一部分)
<Linux开发>系统移植 -之- linux内核移植过程详细记录(第二部分完结)
一、准备BusyBox源码
1、将BusyBox源码压缩包通过FileZilla或其它方式传到Ubuntu中,如下图:
2、解压,命令为:tar -vxjf busybox-1.29.0.tar.bz2
二、BusyBox源码编译前修改
1、修改Makefile,添加编译器
同Uboot和Linux移植一样,打开busybox的顶层Makefile,添加ARCH和CROSS_COMPILE的值,添加后如下所示:
CORSS_COMPILE使用了绝对路径(根据自己实际的交叉编译工具链的安装目录)!!!!主要是为了防止编译出错。。。。。。。
2、busybox中文字符支持
如果默认直接编译busybox的话,在使用SecureCRT的时候中文字符是显示不正常的,中文字符会显示为“?”,比如你的中文目录,中文文件都显示为“?”。busybox中的shell命令对中文输入即显示做了限制,即使内核支持中文但在shell下也依然无法正确显示。
我们需要修改busybox源码,取消busybox对中文显示的限制,打开文件busybox-1.29.0/libbb/printable_string.c,找到函数“printable_string”,修改后如下所示:
红色部分的代码就是被修改以后的,主要就是禁止字符大于 0X7F 以 后 break 和输出‘?’。
打开文件 busybox-1.29.0/libbb/unicode.c 找到" unicode_conv_to_printable2"这个函数,更改后如下:
红色部分的代码就是被修改以后的,同样主要是禁止字符大于 0X7F 的时候设置为‘?’。busybox 中文字符支持跟代码修改有关的就改好了,最后还需要配置 busybox来使能 unicode。
3、配置busybox
先对 busybox 进行默认的配置,有以下几种
配置选项:
①、defconfig,缺省配置,也就是默认配置选项。
②、allyesconfig,全选配置,也就是选中 busybox 的所有功能。
③、allnoconfig,最小配置。
一般使用默认配置即可,因此使用如下命令先使用默认配置来配置一下 busybox:
make defconfig
busybox 也支持图形化配置,通过图形化配置我们可以进一步选择自己想要的功能,输入
如下命令打开图形化配置界面:
make menuconfig
Location:
-> Settings
-> Build static binary (no shared libs)
选项“Build static binary (no shared libs)”用来决定是静态编译 busybox 还是动态编译,静
态编译的话就不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库
文件,但是编译出来的 busybox 会小很多。这里我们不能采用静态编译!因为采用静态编译的
话 DNS 可能会出问题!无法进行域名解析,配置如下图所示:
(2)配置2
置如下路径配置项:
Location:
-> Settings
-> vi-style line editing commands
使能选中,结果如下图所示:
(3)配置3
配置如下路径配置项:
Location:
-> Linux Module Utilities
-> Simplified modutils
默认会选中“Simplified modutils”,这里我们要取消勾选!!结果如下图所示:
(4)配置4
配置如下路径配置项:
Location:
-> Linux System Utilities
-> mdev (16 kb) //确保下面的全部选中,默认都是选中的
结果如下图所示:
(5)配置5
就是使能 busybox 的 unicode 编码以支持中文,配置路径如下:
Location:
-> Settings
-> Support Unicode //选中
-> Check $LC_ALL, $LC_CTYPE and $LANG environment variables //选中
在配置界面,连续按两次“ESC”,就会返回上一级,直到最上层,会提示保存,确认保存即可。
busybox 的配置就到此结束了,大家也可以根据自己的实际需求选择配置其他的选项,不过对于初学者笔者不建议再做其他的修改,可能会出现编译出错的情况发生。
三、编译busybox
配置好 busybox 以后就可以编译了,我们可以指定编译结果的存放目录,我们肯定要将编
译结果存放到自己创建的 rootfs 目录中。
在nfs挂载的目录下创建rootfs目录,命令如下:
cd /home/water/linux/nfs //进入目录
mkdir onefu-rootfs //创建目录
回到源码根目录,然后编译,输入以下命令:
make
make install CONFIG_PREFIX=/home/water/linux/nfs/onefu-rootfs
COFIG_PREFIX 指 定 编 译 结 果 的 存 放 目 录 , 比 如 我 存 放 到“/home/water/linux/nfs/onefu-rootfs”目录中,等待编译完成。编译完成以后如下图所示:
编译完成以后会在 busybox 的所有工具和文件就会被安装到 rootfs 目录中,rootfs 目录内容如下图所示:
从上图可以看出,rootfs 目录下有 bin、sbin 和 usr 这三个目录,以及 linuxrc 这个文件。前面说过 Linux 内核 init 进程最后会查找用户空间的 init 程序,找到以后就会运行这个用户空间的 init 程序,从而切换到用户态。如果 bootargs 设置init=/linuxrc,那么 linuxrc 就是可以作为用户空间的 init 程序,所以用户态空间的 init 程序是 busybox 来生成的。
busybox 的工作就完成了,但是此时的根文件系统还不能使用,还需要一些其他的文件,我们继续来完善 rootfs。
四、补充根文件系统
1、向根文件系统添加 lib 库
(1)向onefu-rootfs 的“/lib”目录添加库文件
Linux 中的应用程序一般都是需要动态库的,当然你也可以编译成静态的,但是静态的可执行文件会很大(前面配置时已选择动态方式了)。如果编译为动态的话就需要动态库,所以我们需要向根文件系统中添加动态库。在 onefu-rootfs 中创建一个名为“lib”的文件夹,命令如下:
mkdir lib
lib 文件夹创建好了,库文件从哪里来呢?lib 库文件从交叉编译器中获取,在我们搭建交叉编译环境的时候将交叉编译器存放到了“/usr/local/arm/”目录中(根据自身安装的位置目录选择)。交叉编译器里面有很多的库文件,这些库文件具体是做什么的我们作为初学者肯定不知道,既然我不知道那就简单粗暴的把所有的库文件都放到我们的根文件系统中。这样做出来的根文件系统肯定很大,如过功底深厚,可做相应的裁剪,否则建议全部放到根文件系统。
进入如下路径对应的目录(即交叉编译工具安装的目录下的lib):
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/water/linux/nfs/onefu-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”查看此文件详详细信息,如下图所示:
从图 38.2.3.1 可以看出,ld-linux-armhf.so.3 后面有个“->”,表示其是个软连接文件,链接
到文件 ld-2.19-2014.08-1-git.so,因为其是一个“快捷方式”,因此大小只有 24B。但是,ld-linuxarmhf.so.3 不能作为符号链接,否则的话在根文件系统中执行程序无法执行!所以我们需要 ldlinux-armhf.so.3 完成逆袭,由“快捷方式”变为“本尊”,方法很简单,那就是重新复制 ld-linuxarmhf.so.3,只是不复制软链接即可,先将 rootfs/lib 中的 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/armlinux-gnueabihf/libc/lib 目录中,重新拷贝 ld-linux-armhf.so.3,命令如下:
cp ld-linux-armhf.so.3 /home/water/linux/nfs/onefu-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 库文件,我们将其也拷贝到 onefu-rootfs/lib 目录中,命令如下:
cp *so* *.a /home/water/linux/nfs/onefu-rootfs/lib/ -d
至此,onefu-rootfs/lib 目录的库文件就这些了,完成以后的 onefu-rootfs/lib 目录如下图所示:
(2)向onefu-rootfs 的“/usr/lib”目录添加库文件
在 onefu-rootfs 的 usr 目录下创建一个名为 lib 的目录,将交叉编译工具安装目录下的xx/linc/usr/lib目录中的库文件拷贝到 onefu-rootfs/usr/lib目录,进入交叉编译工具对应的目录,命令如下:
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib
将此目录下的 so 和.a 库文件都拷贝到 onefu-rootfs/usr/lib 目录中,命令如下:
cp *so* *.a /home/water/linux/nfs/onefu-rootfs/usr/lib/ -d
完成以后的 onefu-rootfs/usr/lib 目录如下图所示:
至此,根文件系统的库文件就全部添加好了,可以使用“du”命令来查看一下 onefu-rootfs/lib 和onefu-rootfs/usr/lib 这两个目录的大小,命令如下:
cd rootfs //进入根文件系统目录
du ./lib ./usr/lib/ -sh //查看 lib 和 usr/lib 这两个目录的大小
可以看出lib和usr/lib这两个文件的大小分别为57MB和67MB,加起来就是57+67=124MB。非常大!所以正点原子的 256MB 和 512MB 的 NAND 核心版就不适合初学者使用,作者选择用的时EMMC版本的开发板。
2、创建其它文件夹
在根文件系统中创建其他文件夹,如 dev、proc、mnt、sys、tmp 和 root 等,创建完成以后如下图所示:
以上完成之后便可设置启动了,但是启动后会有提示错误,接下来,继续补充完善根文件系统。
3、完善根文件系统启动文件
(1)、创建/etc/init.d/rcS 文件
rcS 是个 shell 脚本,Linux 内核启动以后需要启动一些服务,而 rcS 就是规定启动哪些文件的脚本文件。在 onefu-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 文档。
上述代码 中的 rcS 文件内容是最精简的,大家如果去看 Ubuntu 或者其他大型 Linux操作系统中的 rcS 文件,就会发现其非常复杂。因为我们是初步移植,熟悉流程,所以不用搞这么复杂的,而且这么复杂的 rcS 文件也是借助其他工具创建的,比如 buildroot 等。
创建好文件/etc/init.d/rcS 以后一定要给其可执行权限!
进入到目录下,使用如下命令给予/etc/init.d/rcS 可执行权限:
chmod 777 rcS
(2)、创建/etc/fstab 文件
在 rootfs 中创建/etc/fstab 文件,fstab 在 Linux 开机以后自动配ls置哪些需要自动挂载的分区,格式如下:
<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
创建输入完成后保存。
(3)、创建/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支持的动作如下表所示:
动作 | 描述 |
---|---|
sysinit | 在系统初始化的时候process才会执行一次。 |
respawn | 当process终止以后马上启动一个新的。 |
askfirst | 和respawn类似,在运行process之前在控制台上显示“Please press Enter to activate this console.”。只要用户按下“Enter”键以后才会执行process。 |
wait | 告诉init,要等待相应的进程执行完以后才能继续执行。 |
once | 仅执行一次,而且不会等待process执行完成。 |
restart | 当init重启的时候才会执行procee。 |
ctrlaltdel | 当按下ctrl+alt+del组合键才会执行process。 |
shutdown | 关机的时候执行process。 |
process:具体的动作,比如程序、脚本或命令等。
参考busybox的examples/inittab文件,我们也创建一个/etc/inittab,在里面输入如下内容:
#etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::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/inittab文件创建好以后就可以重启开发板即可,至此!根文件系统要创建的文件就已经全部完成了。接下来就要对根文件系统进行其他的测试,比如我们自己编写的软件运行是否正常、是否支持软件开机自启动、中文支持是否正常以及能不能链接等。
五、启动运行测试根文件系统
接下来我们使用测试一下前面创建好的根文件系统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>
server-ip:服务器IP地址,也就是存放根文件系统主机的IP地址,那就是Ubuntu的IP地址,比如我的Ubuntu主机IP地址为192.168.1.144。
root-dir:根文件系统的存放路径,比如我的就是/home/water/linux/nfs/onefu-rootfs。
nfs-options:NFS的其他可选选项,一般不设置。
client-ip:客户端IP地址,也就是我们开发板的IP地址,Linux内核启动以后就会使用此IP地址来配置开发板。此地址一定要和Ubuntu主机在同一个网段内,并且没有被其他的设备使用,在Ubuntu中使用ping命令ping一下就知道要设置的IP地址有没有被使用,如果不能ping通就说明没有被使用,那么就可以设置为开发板的IP地址,比如我就可以设置为192.168.1.145。
server-ip:服务器IP地址,前面已经说了。
gw-ip:网关地址,我的就是192.168.1.1。
netmask:子网掩码,我的就是255.255.255.0。
hostname:客户机的名字,一般不设置,此值可以空着。
device:设备名,也就是网卡名,一般是eth0,eth1….,正点原子的I.MX6U-ALPHA开发板的ENET2为eth0,ENET1为eth1。如果你的电脑只有一个网卡,那么基本只能是eth0。这里我们使用ENET2,所以网卡名就是eth0。
autoconf:自动配置,一般不使用,所以设置为off。
dns0-ip:DNS0服务器IP地址,不使用。
dns1-ip:DNS1服务器IP地址,不使用。
根据上面的格式bootargs环境变量的root值如下:
root=/dev/nfs nfsroot=192.168.1.144:/home/water/linux/nfs/onefu-rootfs,proto=tcp rw ip=192.168.1.145:192.168.1.144:192.168.1.1:255.255.255.0::eth0:off
“proto=tcp”表示使用TCP协议,“rw”表示nfs挂载的根文件系统为可读可写。启动开发板,进入uboot命令行模式,然后重新设置bootargs环境变量,命令如下:
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.144:/home/water/linux/nfs/onefu-rootfs,proto=tcp rw ip=192.168.1.145:192.168.1.144:192.168.1.1:255.255.255.0::eth0:off' //设置bootargs
saveenv //保存环境变量
设置好以后使用“boot”命令启动Linux内核,结果如下图所示:
六、根文件系统测试
1、软件运行测试
首先,在根文件系统下创建一个“drivers”的文件夹,后续的驱动开发文件都可以返点高这个文件夹内。
在ubuntu下使用vim编辑器新建一个hello.c文件,在hello.c里面输入如下内容:
#include
int main(void)
{
while(1){
printf("hello world!\r\n");
sleep(2);
}
return 0;
}
hello.c内容很简单,就是循环输出“hello world”,sleep相当于Linux的延时函数,单位为秒,所以sleep(2)就是延时2秒。编写好以后就是编译,因为我们是要在ARM芯片上运行的,所以要用交叉编译器去编译,也就是使用arm-linux-gnueabihf-gcc编译,命令如下:
arm-linux-gnueabihf-gcc hello.c -o hello
使用arm-linux-gnueabihf-gcc将hello.c编译为hello可执行文件。这个hello可执行文件究竟是不是ARM使用的呢?使用“file”命令查看文件类型以及编码格式:
file hello //查看hello的文件类型以及编码格式
hello是个32位的LSB可执行文件,ARM架构的,并且是动态链接的。所以我们编译出来的hello文件没有问题。将其拷贝到rootfs/drivers目录下,在开发板中输入如下命令来执行这个可执行文件:
cd /drivers //进入drivers目录
./hello //执行hello
2、中文字符测试
(1)设置SecureCRT使用UTF-8编码
因为Linux使用的编码格式为UTF-8,因此要先设置SecureCRT的编码格式。打开Options->Session Options…,打开“Session Options”对话框,选择左侧的“Appearance”,然后在右侧的“Character encoding:”栏选择UTF-8编码,如下图所示:
(2)创建中文文件
在ubuntu中向在rootfs目录新建一个名为“中文测试”的文件夹,然后在SecureCRT下查看中文名能不能显示正确。输入“ls”命令,结果如下图所示:
可以看出“中文测试”这个文件夹显示正常,接着“touch”命令在“中文测试文件夹”文件夹中新建一个名为“测试文件.txt”的文件,并且使用vim编辑器在其中输入“你好,OneFu电子设计工作室”,借此来测试一下中文文件名和中文内容显示是否正常。在SecureCRT中使用“cat”命令来查看“测试文件.txt”中的内容,结果如下图所示:
可以看出,“测试文件.txt”的中文内容显示正确,而且中文路径也完全正常,说明我们的根文件系统已经支持中文了!
3、开机自启动测试
前面测试hello软件的时候都是等Linux启动进入根文件系统以后手动输入命令“./hello”来完成的。我们一般做好产品以后都是需要开机自动启动相应的软件,本节我们就以hello这个软件为例,讲解一下如何实现开机自启动。前面我们说过了,进入根文件系统的时候会运行/etc/init.d/rcS这个shell脚本,因此我们可以在这个脚本里面添加自启动相关内容。添加完成的/etc/init.d/rcS文件内容如下:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
runlevel=S
umask 022
export PATH LD_LIBRARY_PATH runlevel
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
#开机自启动
cd /drivers
./hello &
cd /
第16行,进入drivers目录,因为要启动的软件存放在drivers目录下。 第17行,以后台方式执行hello这个软件。 第18行,退出drivers目录,进入到根目录下。 自启动代码添加完成以后就可以重启开发板,看看hello这个软件会不会自动运行。结果如下图所示:
由上图可看出,自动运行启动成功。
4、外网连接测试
使用ping命令连接百度的官网:www.baidu.com,输入下面命令:
ping www.baidu.com
结果如下图所示:
可以看出,测试失败,提示www.baidu.com是个“bad address”,也就是地址不对,显然我们的地址是正确的。之所以出现这个错误提示是因为www.baidu.com的地址解析失败了,并没有解析出其对应的IP地址。我们需要配置域名解析服务器的IP地址,一般域名解析地址可以设置为所处网络的网关地址,比如192.168.1.1。也可以设置为114.114.114.114,这个是运营商的域名解析服务器地址。
在onefu-rootfs中新建文件/etc/resolv.conf,然后在里面输入如下内容:
nameserver 114.114.114.114
nameserver 192.168.1.1
设置很简单,nameserver表示这是个域名服务器,设置了两个域名服务器地址:114.114.114.114和192.168.1.1,大家也可以改为其他的域名服务器试试。如果使用“udhcpc”命令自动获取IP地址,“udhcpc”命令会修改nameserver的值,一般是将其设置为对应的网关地址。修改好以后保存退出,重启开发板!重启以后重新ping一下百度官网,结果如下图所示:
可以看出ping百度官网成功了!域名也成功的解析了,至此!我们的根文件系统就彻底的制作完成,这个根文件系统最好打包保存一下,防止以后做实验不小心破坏了根文件系统而功亏一篑,又得从头制作根文件系统。uboot、Linux kernel、rootfs这三个共同构成了一个完整的Linux系统,现在的系统至少是一个可以正常运行的系统,后面我们就可以在这个系统上完成Linux驱动开发的学习。
以上内容均参考正点原子linux开发板配套资料,如有不足,遗漏,错误之处,可联系作者,进一步改善。
如若获取更详细的资料可到正点原子官方网址下载。