上篇内容使用busybox制作好了根文件系统,接下来需要进行一些测试和功能的完善!
根文件系统的测试
测试根文件系统的时候不是直接烧写到EMMC里面,这样测试效率太低了,Ubuntu的rootfs目录已经保存了根文件系统,只需要在开发板上通过nfs挂载Ubuntu下的rootfs目录即可。也就是说,根文件系统一直在Ubuntu下,开发板通过网络在使用这个根文件系统,这样方便开发调试。
采用挂载网络根文件系统,使用NFS。要求:
1、linux内核网络驱动要工作正常。
2、设置uboot的bootargs,也就是linux内核的命令行参数。
从ubuntu的tftp里面加载我们前面移植的uboot、zImage和dtb,设置bootcmd。
前提设置
在开发板上设置网络相关变量确保网络正常使用,下面是我根据Ubuntu上IP和开发板IP的设置参数。
setenv serverip '192.168.3.200'
setenv gatewayip '192.168.3.254'
setenv netmask '255.255.255.0'
setenv ipaddr '192.168.3.167'
setenv ethaddr '32:34:46:78:9A:DC'
saveenv
设置使用tftp服务(tftp服务的搭建看这里)加载镜像zImage和dtb。将所要用到的zImage 和imx6ull-14x14-evk-emmc.dtb文件放到Ubuntu上tftp服务的共享目录中。
setenv bootcmd 'tftp 80800000 zImage;tftp 83000000 imx6ull-14x14-evk-emmc.dtb;bootz 80800000 - 83000000'
保存环境变量
saveenv
设置ubuntu上NFS服务支持低版本运行
在Ubuntu上,输入下面命令打开/etc/default/nfs-kernel-server
文件
vim /etc/default/nfs-kernel-server
Ubuntu18的 nfs默认只支持3和4版本的nfs,uboot默认使用的是版本2,所以直接修改Ubuntu上的nfs配置,否则nfs根文件系统无法挂载。然后在最后面添加下面这一行:
RPCNFSDOPTS="--nfs-version 2,3,4 --debug --syslog"
添加完成以后保存退出,输入如下命令重启NFS服务即可:
sudo /etc/init.d/nfs-kernel-server restart
bootargs环境变量设置
接下来要启动开发板,在mobaxterm上操作了。
主要是设置里面的root
值,将root
的值改为NFS挂载即可。在Linux内核源码里面有相应的文档讲解如何设置,文档为内核目录下Documentation/filesystems/nfs/ nfsroot.txt
,格式如下:
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>
:服务器IP地址,就是Ubuntu的IP地址。
:根文件系统的存放路径,这里我的是/home/workdir/rootfs
:NFS的其他可选选项,一般不设置。
:客户端IP地址,即开发板的IP地址, 此地址一定要和Ubuntu的IP在同一个网段且没有被其他设备使用。
:服务器IP地址,Ubuntu的IP地址。
:网关地址
:子网掩码,教程中就是255.255.255.0。
:客户机的名字,一般不设置,此值可以空着。
:设备名,也就是网卡名,一般是eth0,eth1….,正点原子STM32MP157开发板
只有一个网口,名字为eth0。
:自动配置,一般不使用,所以设置为off。
:DNS0服务器IP地址,不使用。
:DNS1服务器IP地址,不使用。
根据上面的格式,bootargs环境变量的root值如下:
root=/dev/nfs nfsroot=192.168.3.200:/home/workdir/rootfs,proto=tcp rw ip=192.168.3.167:192.168.3.200:192.168.3.1:255.255.255.0::eth0:off
proto=tcp
表示使用TCP协议,rw
表示nfs挂载的根文件系统为可读可写。
通过上面的了解,我们设置参数使用的命令如下:
启动开发板,进入uboot命令行模式,然后重新设置bootargs环境变量,命令如下:
setenv bootargs 'console=ttymxc0,115200 rw root=/dev/nfs nfsroot=192.168.3.200:/home/workdir/rootfs,proto=tcp ip=192.168.3.167:192.168.3.200:192.168.3.1:255.255.255.0::eth0:off'
将上述的环境变量设置好后,要注意保存!!
saveenv
查看环境变量
查看设置后的环境变量,是否正确设置。
print
确保上面的没有问题后,接下来输入boot
命令开始启动
boot
如下图刚开始启动:
最终画面如下图:
可以看到根文件系统已经挂载成功了。
完善根文件系统
创建/etc/init.d/rcS文件
can't run '/etc/init.d/rcS': No such file or directory
提示很简单,说是无法运行/etc/init.d/rcS
这个文件,因为这个文件不存在。如下图所示:
在ubunru下,根文件系统的/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
对上述参数的简单理解如下:
PATH环境变量保存着可执行文件可能存在的目录,这样在执行一些命令或者可执行文件的时候就不会提示找不到文件这样的错误。LD_LIBRARY_PATH环境变量保存着库文件所在的目录。使用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
以后一定要给其可执行权限!使用如下命令给予权限:
chmod 777 rcS
设置好以后就重新启动Linux内核,启动以后如下图所示:
从上图可以看到,提示找不到/etc/fstab
文件,还有一些其他的错误,先把/etc/fstab
这个错误解决了。前面说了mount -a
挂载所有根文件系统的时候需要读取/etc/fstab
,因为/etc/fstab
里面定义了该挂载哪些文件,接下来就是创建/etc/fstab
文件。
创建/etc/fstab文件
在rootfs中创建/etc/fstab文件,fstab在Linux开机以后自动配置哪些需要自动挂载的分区,格式如下:
:要挂载的特殊的设备,也可以是块设备,比如/dev/sda等等。
:挂载点。
:文件系统类型,比如ext2、ext3、proc、romfs、tmpfs等等。
:挂载选项,在Ubuntu中输入“man mount”命令可以查看具体的选项。一般使用defaults,也就是默认选项defaults包含了rw、suid、dev、exec、auto、nouser和async。
:为1的话表示允许备份,为0不备份,一般不备份,因此设置为0。
:磁盘检查设置,为0表示不检查。根目录‘/’设置为1,其他的都不能设置为1,其他的分区从2开始。一般不在fstab中挂载根目录,因此这里一般设置为0。
按照上述格式,/etc/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/init.d/rcS脚本第11行出现问题,提示不能创建“/proc/sys/kernel/hotplug”,这个是Linux内核配置问题,最后在讲解怎么处理。接下来还需要创建一个文件/etc/inittab。
创建/etc/inittab文件
init程序会读取/etc/inittab
这个文件,inittab
由若干条指令组成。每条指令的结构都是一样的,以“:”分隔的4个段组成,格式如下:
:::
:每个指令的标识符,不能重复。但是对于busybox的init来说, ,有着特殊意义。对于busybox而言用来指定启动进程的控制tty,一般将串口或LCD屏幕设置为控制tty。
:对busybox来说此项完全没用,所以空着。
:动作,用于指定可能用到的动作。busybox支持的动作如下图所示:
:具体的动作,比如程序、脚本或命令等。
/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作为控制台终端,也就是ttySTM0。第4行,重启的话运行/sbin/init。第5行,按下ctrl+alt+del组合键的话就运行/sbin/reboot,看来ctrl+alt+del组合键用于重
启系统。第6行,关机的时候执行/bin/umount,也就是卸载各个文件系统。第7行,关机的时候执行/sbin/swapoff,也就是关闭交换分区。
操作如下图:
/etc/inittab
文件创建好重启开发板即可。根文件系统要创建的文件就已经全部完成了!!
重启开发板,如下图:
从上图可以看出,没有任何错误提示,说明根文件系统工作已经正常了。
根文件系统其他功能测试
软件运行测试
使用Linux系统的目的就是运行自己的软件,编译的应用软件一般都使用动态库,使用动态库的话应用软件体积就很小,但是得提供库文件,库文件已经添加到了根文件系统中。可以编写一个小小的测试软件来测试一下库文件是否工作正常,在根文件系统下创建一个名为“drivers”的文件夹,以后学习 Linux驱动的时候就把所有的实验文件放到这个文件夹里面。
在Ubuntu下使用vim编辑器新建一个hello.c文件,输入如下内容:
#include <stdio.h> int main(void)
{ while(1){ printf("hello world!\r\n"); sleep(2); } return 0;
}
用交叉编译器去编译,也就是使用arm-linux-gnueabihf-gcc编译,命令如下:
arm-linux-gnueabihf-gcc hello.c -o hello
使用arm-linux-gnueabi-gcc将hello.c编译为hello可执行文件。
在开发板上执行 hello
程序成功运行了,结果如下图所示:
可以看出, hello这个软件运行正常,说明根文件系统中的共享库是没问题的,要想终止hello的运行,按下“ctrl+c”组合键即可。
中文字符测试
在ubuntu中向在rootfs目录新建一个名为chinese.txt的文件在里面输入中文,然后在MobaXterm下查看这个文件里的内容。结果如下图所示:
从上图可以看出文件里中文内容显示正确,而且中文路径也完全正常,说明根文件系统已经完美支持中文了!
开机自启动测试
在之前测试hello软件的时候都是等Linux启动进入根文件系统以后手动输入命令“./hello”来完成的。一般做好产品以后都是需要开机自动启动相应的软件,本节就以hello这个软件为例,讲解一下如何实现开机自启动。前面说过,进入根文件系统的时候会执行/etc/init.d/rcS
这个shell文件,因此可以在这个脚本里面添加要执行的shell命令。添加完成以后的/etc/init.d/rcS文件内容如下:
重启开发板,结果如下图所示:
从上图可看出,hello开机自动运行,证明开机自启动成功。
外网连接测试
这里说的外网是百度、淘宝等这些网站的测试。也
就是说看看开发板能不能上网,能不能和局域网外的这些网站进行通信。测试方法很简单,就是通过ping命令来ping一下百度的官网:www.baidu.com。输入如下命令:
ping www.baidu.com
结果是失败的,提示“bad address”,如下图:
出现这个错误提示是因为 www.baidu.com的地址解析失败了,并没有解析出其对应的IP地址。需要配置域名解析服务器的IP地址,一般域名解析地址可以设置为所处网络的网关地址,比如192.168.1.1。 也可以设置为114.114.1144.114,这个是运营商的域名解析服务器地址。
如何解决
在rootfs中的/etc
目录下创建resolv.conf
,然后在里面输入如下内容:
nameserver 114.114.114.114
nameserver 192.168.3.1
设置很简单,nameserver表示这是个域名服务器,设置了两个域名服务器地址:114.114.114.114和192.168.1.1,也可以改为其他的域名服务器试试。
将上述文件,保存后退出。重启开发板!重启以后重新ping一下百度官网,成功ping通。结果如下图所示:
可以看出ping百度官网成功了!域名也成功的解析了,至此!根文件系统就彻底的制作完成。