前言
在前面的文章中,完成了uboot和内核的基本移植教程,为驱动的学习打下了一定的基础。为了后期更好的学习,本篇文章记录了最小文件系统的制作、nfs挂载根文件系统教程,搭建一个方便驱动教程学习的环境。
注:本文开发环境均基于ubuntu18.04 LTS平台搭建。
交叉编译工具安装
说明
后期所有程序都是在开发板上运行的,基于ARM Coretex-A9的exynos 4412,而我们开发机是X64平台,所以需要安装交叉编译链,编译出能在开发板上运行的可执行二进制。
安装
在最新的ubuntu18.04 LTS平台上,arm版的gcc已经收录到官方源里面,可以直接执行熟悉的apt install 便可以安装gcc交叉编译工具链,下面给出安装流程与说明。
- 安装命令
$ sudo apt install gcc-arm-linux-gnueabihf
- 安装文件说明
安装好后会在/usr/arm-linux-gnueabihf目录下生成以下文件夹:
$ bin include lib
- bin目录下是软链接到/usr/bin/arm-linux-gnueabihf-*(*为gcc,ar等等)
- include目录下是头文件
- lib目录下是gcc的库文件,有动态和静态库。
最小根文件系统制作
在安装好arm-linux-gnueabihf-交叉编译工具链后,便可进行最小根文件系统的制作。
下载
本文以官方最新稳定版14 February 2019 -- BusyBox 1.30.1 (stable)为例,进行最小跟文件系统的制作,制作流程参阅讯为官方手册《Linux系统编程_v2.2.pdf》[1]。
流程
$ tar -xvf busybox-1.30.1.tar.bz2
$ cd ../busybox-1.30.1/
$ make menuconfig
$ 作相应配置,见下面的说明
$ make -j8
$ make install
$ 完善最小根文件系统,同见下面的说明
说明
配置说明
-
选中Settigs目录:
-
指定交叉编译链前缀和指定install目录
- 其他设置(可选)
其他配置项中可以选着安装的软件包,根据自己需要自行配置。
完善最小根文件系统
- 创建必需的文件夹
$ mkdir dev etc lib mnt proc sys tmp var
- 完善etc目录
-
目录如下:
注:图片中的绿色文件的权限均为0755,必须设置!
- 在内核加载完成后启动的第一个进程init进程,会读取并执行
init.d/rcS
, 该文件内容如下:
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
#
# Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP
/bin/hostname iTOP-4412
#/bin/mount -n -t proc none /proc
#/bin/mount -n -t sysfs none /sys
#/bin/mount -n -t usbfs none /proc/bus/usb
#/bin/mount -t ramfs none /dev
[ -e /proc/1 ] || /bin/mount -n -t proc none /proc
[ -e /sys/class ] || /bin/mount -n -t sysfs none /sys
[ -e /dev/tty ] || /bin/mount -t ramfs none /dev
echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s
#/bin/hotplug
# mounting file system specified in /etc/fstab
mkdir -p /dev/pts
mkdir -p /dev/shm
/bin/mount -n -t devpts none /dev/pts -o mode=0622
/bin/mount -n -t tmpfs tmpfs /dev/shm
#/bin/mount -n -t ramfs none /tmp
#/bin/mount -n -t ramfs none /var
mkdir -p /var/empty
mkdir -p /var/log
mkdir -p /var/log/boa
mkdir -p /var/lock
mkdir -p /var/run
mkdir -p /var/tmp
ln -sf /dev/ttyS2 /dev/tty2
ln -sf /dev/ttyS2 /dev/tty3
ln -sf /dev/ttyS2 /dev/tty4
syslogd
/etc/rc.d/init.d/netd start
echo " " > /dev/tty1
echo "Starting networking..." > /dev/tty1
#sleep 1
#/etc/rc.d/init.d/httpd start
#echo " " > /dev/tty1
#echo "Starting web server..." > /dev/tty1
#sleep 1
#/etc/rc.d/init.d/leds start
#echo " " > /dev/tty1
#echo "Starting leds service..." > /dev/tty1
#echo " "
#sleep 1
/sbin/ifconfig lo 127.0.0.1
/etc/init.d/ifconfig-eth0
#echo 0 > /proc/sys/kernel/hung_task_timeout_secs
- 完善网卡配置相关文件
- ifconfig-eth0文件内容如下:
IP=192.168.1.141
Mask=255.255.255.0
Gateway=192.168.1.1
DNS=192.168.1.1
MAC=08:90:90:90:90:90
- init.d/ifconfig-eth0文件内容如下:
#!/bin/sh
echo -n Try to bring eth0 interface up......>/dev/ttySAC2
if [ -f /etc/eth0-setting ] ; then
source /etc/eth0-setting
if grep -q nfs /proc/mounts ; then
echo -n NFS root ... > /dev/ttySAC2
else
ifconfig eth0 down
ifconfig eth0 hw ether $MAC
ifconfig eth0 $IP netmask $Mask up
route add default gw $Gateway
fi
echo nameserver $DNS > /etc/resolv.conf
else
if grep -q "^/dev/root / nfs " /etc/mtab ; then
echo -n NFS root ... > /dev/ttySAC2
else
/sbin/ifconfig eth0 192.168.253.12 netmask 255.255.255.0 up
fi
fi
echo Done > /dev/ttySAC2
- rc.d/init.d/netd文件内容如下:
#!/bin/sh
base=inetd
# See how we were called.
case "$1" in
start)
/usr/sbin/$base
;;
stop)
pid=`/bin/pidof $base`
if [ -n "$pid" ]; then
kill -9 $pid
fi
;;
esac
exit 0
- 环境变量配置
profile文件内容如下:
# Ash profile
# vim: syntax=sh
# No core files by default
ulimit -S -c 0 > /dev/null 2>&1
USER="`id -un`"
LOGNAME=$USER
PS1='[$USER@$HOSTNAME]# '
PATH=$PATH
HOSTNAME=`/bin/hostname`
export USER LOGNAME PS1 PATH
- 用户配置
passwd文件内容如下:
root:*:0:0:root:/:/bin/sh
bin:*:1:1:bin:/bin:
daemon:*:2:2:daemon:/sbin:
nobody:*:99:99:Nobody:/:
设置相关文件权限
注:必须修改新建的文件权限,这里推荐设置为0755(rwxr-xr-x),下面命令以安装好的最小根文件系统文件夹为root,在其下的etc文件夹里执行.
$ chmod 0755 eth0-setting passwd profile init.d/* rc.d/init.d/*
拷贝库文件
因为使用的交叉编译环境和编译内核的相同,Busybox 编译生成的二进制文件是以动态链接库的形式运行,所以需要拷贝编译器里面的库文件到 lib 目录,使用下面的命令:
$ cp /usr/arm-linux-gnueabihf/lib/* lib -a
注:命令以安装好的最小根文件系统文件夹为root,在其下执行。
nfs挂载根文件系统
开发板端NFS配置
在上面的init.d/ifconfig-eth0
配置为了nfs启动,eth0-setting
中对网卡的IP做了相应配置,需要和linux内核中的启动参数相对应,否者无法以NFS方式挂载根文件系统,需要在内核启动参数中填入参数,具体如下:
Boot options --->
...
Kernel command line type... --->
(root=/dev/nfs rw nfsroot=192.168.1.140:/home/jason/arm-devlop/system ip=192.168.1.141:192.168.1.140:192.168.1.1:255.255.255.0:itop:eth0:off rootfstype=ext4 init=/linuxrc console=ttySAC2,115200)
Kernel command line type... --->
...
开发机端NFS配置
- 安装nfs-kernel-server
$ sudo apt install nfs-kernel-server
- 配置NFS服务器参数
- 在/etc/exports文件写入新的一行,内容如下:
/home/jason/arm-devlop/system/ *(rw,sync,no_root_squash,no_subtree_check)
- 挂载不上
发现开发机能够挂在自己的NFS文件系统,但是开发板不能挂载,尝试挂载Ubuntu12版本的却可以,经过查阅资料后发现,从Ubuntu17.04开始,nfs默认只支持协议3和协议4,而kernel中默认支持协议2,所以才会出现挂载失败的情况[2],在/etc/default/nfs-kernel-server加入如下内容,使其支持2,3,4版本即可。
RPCNFSDOPTS="--nfs-version 2,3,4 --debug --syslog"
- 重启服务
$ sudo systemctl restart nfs-kernel-server.service
效果展示
参考资料
[1] 讯为官方手册《Linux系统编程_v2.2.pdf》
[2] 开发板挂载 ubuntu18.04系统下的 nfs根文件系统失败