(一)准备工作
- Ubuntu 16.04系统
- linux-3.5内核:linux-3.5-20190929
- 交叉编译工具arm-linux-gcc-4.5.1-v6-vfp-20120301.rar
- busybox源码包:busybox-1.21.1.rar
(二)工具介绍
(1)交叉编译器
这个其实之前就已经讲过了,不懂的参考我的另一篇文章linux安装交叉编译环境
交叉编译器和本地编译器是相对应的概念,在嵌入式开发的时候,由于目标板的资源有限,我们一般在电脑上编译好在目标板上运行的程序,然后下到板子里,这就需要用到交叉编译器的概念。具体的
(2)NFS文系统
NFS(NetWork Filesystem System)文件系统是基于 网络传输文件,在嵌入式领域应用十分广泛,可以用于主机和嵌入式设备之间无缝传输文件。
NFS服务是基于客户端和服务器模式,NFS服务器是提供输出文件(共享文件)的计算机。NFS客户端是访问输出文件的计算机,它可以将输出目录挂载到自己系统中的某个目录中,然后像访问本地文件一样去访问NFS服务器中的输出文件。
关于NFS的具体教程可以参考NFS网络文件系统详解,不过本节我们直接使用,并不影响我们操作。
(3)busybox的作用
Busybox是一个集成了上百个常用linux命令和工具的软件,是一个遵循GPL协议开源项目。Busybox将众多的UNIX命令集合进一个很小的可执行程序中,与相应的GNU工具相比,所能提供的选项比较少,但是也足够一般的应用了,Busybox主要用于嵌入式系统,是一个“万能工具”,可使用在数字电视、mp3、音响、小型服务器等嵌入式产品中。
在使用Busybox创建根文件系统的时候,只需要在/dev目录下创建必要的设备节点,在/etc目录下增加一些配置文件即可,当然,如果Busybox使用动态链接,那么还需要再/lib目录下包含库文件。
(三)制作步骤
(1)安装交叉编译器
(2)搭建NFS服务器
- 安装nfs服务
$ sudo apt-get install nfs-kernel-server nfs-common
- 修改配置文件
$ sudo vim /etc/exports
注:“exports”文件用于配置NFS服务器中输出的共享目录
修改内容如下:
/driver/rootfs *(rw,sync,no_root_squash,no_subtree_check)
注:/root/rootfs为与nfs服务客户端共享的目录,可自行创建,这个路径必须为绝对路径。
*:允许所有的网段访问,也可以使用具体的IP
192.168.1.* 指定网段,在该网段中的用户可以挂载
ro : 只读
rw:挂接此目录的客户端对该共享目录具有读写权限
sync:资料同步写入内存和硬盘
no_root_squash:root用户具有对根目录的完全管理访问权限。
no_subtree_check:不检查父目录的权限
3.重启nfs服务和rpcbind 服务
$ sudo /etc/init.d/nfs-kernel-server restart
$ sudo /etc/init.d/rpcbind restart
(3)NFS服务的测试
1.检查客户端和服务端的网络是否连通(ping命令)
ping 服务主机IP
//可以使用windows 的命令行ping你的虚拟机
//有另一台虚拟机的可以使用别的虚拟机
2.查看服务端的共享目录
showmount -e 服务主机IP
//虚拟机linux操作
3.将与nfs服务客户端共享的目录挂载到本地
mount -t nfs -o nolock 服务主机IP:目标机的共享目留 /mnt
//虚拟机linux操作
注:/mnt 指定将共享目录挂载的路径, -t nfs 指定挂在协议是那台ip地址的主机,mount nfs时,默认选项包括文件锁,依赖于portmap提供的动态端口分配功能,因此需要解锁,因此一般直接在指令中直接加上-o nolock。
4.通过访问/mnt即可访问共享目录的内容
ls /mnt
//虚拟机linux操作
5.取消挂载
umount /mnt
注:/mnt 指定将共享目录挂载的路径,要和挂载时的路径相同。
(四)busybox安装
-
在Ubuntu系统根目录新建driver目录
-
将busybox-1.21.1.rar在windows解压后,复值到虚拟机的driver目录下
-
对busybox-1.21.1.tar.bz2进行指令解压
tar -xvf busybox-1.21.1.tar.bz2
- 配置 BusyBox
a) cd busybox-1.21.1.
b) apt-get install libncurses5-dev
注:ubuntu系统缺ncurses devel(提供字符终端处理库),下载安装即可
c) make menuconfig
d) 设置共享库
通过键盘的左右键选择select、Exit、help,之后通过enter确定选择,进行界面的切换。
Busybox Settings —>Build Options —>[*] Build shared libbusybox
按空格选中这个
e) 指定交叉编译链(注意 arm-linux-后面不要有空格)
Busybox Settings —>Build Options —>() Cross Compiler prefix (NEW)
f) 设置安装路径(路径指定为绝对路径,为安装生成的根文件系统,目录层次不要太深,方便之后使用)
Busybox Settings —>
Installation Options (“make install” behavior) —>
(./install) BusyBox installation prefix(NEW)
g) 添加模块指令
5. 编译安装并检测
# make && make install
# file bin/busybox
通过编译和安装,会在/driver/目录下生成一个相应的rootfs目录,改目录下有bin、linuxrc、sbin、usr四个目录。
6.完善动态链接库
前面操作中busybox设置的是动态链接库,编译器采用的是arm-linux-gcc,找到安装arm-linux-gcc的安装路径:
root@linux:/driver/rootfs# which arm-linux-gcc
/opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-gcc
上面是我的路径,这个就是要复制出来的动态库的路径,而在linux系统下,不同的目录有着不同的存储作用,先模仿ubuntu系统,在rootfs 下面新建需要的目录:
root@linux:/driver/rootfs# mkdir dev ./etc/init.d home proc sys root opt tmp var lib -p
root@linux:/driver/rootfs# cp -rf /opt/FriendlyARM/toolschain/4.5.1/arm-none-linux-gnueabi/lib/*.so* ./lib
(五)构建根文件系统
上面介绍了如何安装Busbybox,建立了bin、linuxrc、sbin、usr等目录,最小根文件系统的大部分目录已经建好,现在开始我们制作根文件系统。
1.构建etc目录
etc/主要是存放系统的配置文件,内核在启动和运行过程中需要读取这些配置文件。之前学习进程章节中知道init的进程号为1,是所有进程的父进程,内核初始化完毕之后,init程序开始运行。其他软件也同时开始运行。init程序通过/etc/inittab文件进行配置、创建其他子进程,比如调用脚本文件配置IP地址、挂接其他文件系统,最后启动shell等。etc目录下的内容取决于要运行的程序,本节只需要创建3个文件:etc/inittab、etc/init.d/rcS、etc/fstab。
(1) 配置inittab文件
etc/inittab属于一个运行时配置文件,实际工作的时候 busybox 会解析这个 inittab 文本文件,然后根据解析的内容来决定所要进行的工作,inittab 的格式在 busybox 中定义。
root@linux:/driver/rootfs# cp /driver/busybox-1.21.1/examples/inittab /driver/rootfs/etc/
root@linux:/driver/rootfs# vim /driver/rootfs/etc/inittab
注释或删除里面的内容,只保留以下4行:
::sysinit:/etc/init.d/rcS //是init进程启动的第一个子进程,它是一个脚本
console::askfirst:-/bin/sh //启动shell,以/dev/console作为控制台
::ctrlaltdel:/sbin/reboot //当按下 Ctrl+Alt+Delete 组合键时, init重启执行程序
::shutdown:/bin/umount -a -r
关机时运行 umount 命令卸载所有的文件系统,如果卸载失败,试图以只读方式重新挂载
(2) 配置fstab文件
执行mount –a时挂接/etc/fstab指定的文件系统,linux下的etc目录是用来存放系统配置信息以及软件安装配置信息,相当于windows下的注册表
root@linux:/driver/rootfs# cp /etc/fstab /driver/rootfs/etc/
修改内容如下:
# device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
device:要挂载的设备
注: tmpfs 是一个临时文件系统,驻留于你的交换分区或是内存中(取决于你的使用情况)。使用它可以高文件访问速度,并能保证重启时会自动清除这些文件。
mount point :设备挂载目录,需要挂载的文件系统的挂载点
type :要挂载设备或是分区的文件系统类型
options:挂载参数(noauto,auto、user、exec、ro、rw)对于大多数系统使用”defaults”就可以
常用参数:
auto:执行mount –a时自动挂载
noauto:执行mount –a时不挂载
user:允许普通用户挂载设备
nouser:只允许root用户挂载设备
exec:允许挂载设备上的程序
Ro:以只读方式挂载文件系统
rw:以只写方式挂载文件系统
sync:修改文件时,会自动写入设备
default:rw、exec、auto、nouser、async的组合
dump:是否提供备份功能,0为不备份,1为要备份
pass:是否开机时对文件系统进行检查,该字段被fsck命令用来决定在启动时需要被扫描的文件系统的顺序,根文件系统”/”对应该字段的值应该为1,其他文件系统应该为2。若该文件系统无需在启动时扫描,则设置该字段为0
(3) 配置rcS文件(此文件存放在rootfs下的etc目录中的init.d目录下)
rcS为脚本文件,在init配置文件中定义了此为第一个要执行的程序,那就最先执行。可以在此脚本中添加自动执行的命令,内容如下:
#!/bin/sh
/bin/mount -a
mkdir -p /dev/pts //将文件 /etc/fstab 中指明的文件挂载到对应的挂载点
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug //热插拔事件时产生设备节点的支持
mdev -s //在/dev目录下生成内核支持的所有设备的结点
/bin/hostname ubuntu //Ubuntu为主机名,自己定义
(4) 配置profile文件
inittab中执行了这样一个语句“::respawn:-/bin/sh”。启动/bin/sh程序时会启动ash的配置信息,而它就是/etc/profile,sh会把profile的所有配置全部都运行一遍,因此用户可以把自己的启动程序放在这里。配置内容如下:
USER="`id -un`"
LOGNAME=$USER
PS1='[\u@\h \W]# '
PATH=$PATH
HOSTNAME=`/bin/hostname` #不要少了“`”这个符号
export USER LOGNAME PS1 PATH
注:这个文件是添加环境变量,以实现控制台终端命令提示符号模板功能,这些命令包含用户\u,用户名配置需要etc/group 和etc/passwd两个文件,可直接从虚拟机的 Linux 系统的 /etc 目录中复制这两个文件到自己开发板根文件系统 etc 目录。
root@linux:/driver/rootfs# cp /etc/group /etc/passwd /driver/rootfs/etc/
(5) 创建控制台设备文件和万能垃圾桶
两个设备文件在内核挂载完文件系统后,系统会利用mdev自动创建,可是在此之前,即在内核挂载文件系统之前。init进程会用到这两个设备文件。如果没有这两个设备文件会提示如下一些信息
root@linux:/driver/rootfs# ls -l /dev/console /dev/null
crw------- 1 root root 5, 1 4月 8 11:51 /dev/console
crw-rw-rw- 1 root root 1, 3 4月 8 11:51 /dev/null
root@linux:/driver/rootfs# mknod dev/console c 5 1
root@linux:/driver/rootfs# mknod dev/null c 1 3
注:/dev/console创建的文件是字符设备(c),主设备号是5,次设备号是1,只能用mknod命令创建,其作用是通过串口向内核传送命令的平台;同理/dev/null,/dev/null看作"黑洞",等价于一个只写文件,所有写入内容都会永远丢失。
(6) 修改配置文件权限
root@linux:/driver/rootfs/etc# pwd
/driver/rootfs/etc
root@linux:/driver/rootfs/etc# ls
fstab group init.d inittab passwd profile
root@linux:/driver/rootfs/etc# ls ./init.d/
rcS
root@linux:/driver/rootfs/etc# chmod +x fstab inittab ./init.d/rcS
(7) NFS文件系统挂接
由于前面的操作已经在系统安装时已经安装 NFS 服务器,所以只需要配置和启动服务即可编辑/etc/exports 文件加入允许其它计算机访问的目录和访问权限(注意是Ubuntu系统下的etc 目录)。
root@linux:/driver/rootfs/etc# vim /etc/exports
输入以下内容:
/driver/rootfs/ *(rw,sync,no_root_squash,no_subtree_check)
注意:目录与 IP 之间用<Tab>键
(8) 关 linux 防火墙
a) 检查防火墙的状态
root@linux:/driver/rootfs/etc# ufw status
若状态为不活跃,证明防火墙已经关闭,否则执行:ufw disable
到目前为止跟文件系统已经制作成功。
(六)下载测试
我们下载到tiny4412开发板测试一下:
在下载之前还要设置IP地址:
(1) windows静态ip设置
(2)关闭windows防火墙
(3)虚拟机的网络设置
虚拟机工具栏–>编辑–>虚拟网络编辑器
虚拟机工具栏–>编辑
(4)配置Ubuntu ip
root@linux:~# ifconfig ens33 192.168.1.2
root@linux:~# /etc/init.d/networking restart
(5)链接串口,进入uboot交互模式,设置启动参数
在终端输入
set bootargs 'noinitrd root=/dev/nfs nfsroot=192.168.1.2:/driver/rootfs ip=192.168.1.5:192.168.1.2:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0 lcd=S70'
注意:此操作为一行指令,不要有换行,可以放到文本中取消换行
NFS文件夹具体的路径
nfsroot=192.168.1.2:/driver/rootfs ip=192.168.1.5:192.168.1.2:192.168.1.1:255.255.255.0::eth0:off
格式说明:
nfsroot=虚拟机Linux系统IP:根文件系统绝对路径 ip=开发板IP:虚拟机Linux系统IP:网关:子网掩码::开发板的网卡设备名(一般是eth0,不是虚拟机):off
保存:
save