Qemu仿真----(1)挂载网络文件系统
使用Qemu仿真开发板,挂在网络内核和根文件系统。
平台:ubuntu 16.04
对象:Qemu仿真ARM32.
文件:linux-4.4.300.tar.xz、busybox-1.27.1.tar.bz2、u-boot-2017.05.tar.bz2
1.安装依赖
$ sudo apt install libc6-dev bison flex bc gawk texinfo git unzip build-essential vim tree curl wget ssh libncurses5-dev diffutils $ sudo apt install u-boot-tools $ sudo apt install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi $ sudo apt install qemu-system-arm
我们查看qemu支持的开发板
$ ./qemu-system-arm -M help
2.下载资源
2.1 kernel
[https://kernel.org/]
或
[http://mirrors.ustc.edu.cn/kernel.org/linux/kernel/]
2.2 busybox
[https://busybox.net/downloads/]
2.3 u-boot
[https://ftp.denx.de/pub/u-boot/]
3.编译内核
3.1 解压文件
$ tar -xvf linux-4.4.300.tar.xz $ cd linux-4.4.300
3.2 修改Makefile
@@ -254,8 +254,10 @@ SUBARCH := $(shell uname -m | sed -e s/i # "make" in the configured kernel build directory always uses that. # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile -ARCH ?= $(SUBARCH) -CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) +# ARCH ?= $(SUBARCH) +# CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) +ARCH ?= arm +CROSS_COMPILE ?= arm-linux-gnueabi- # Architecture as present in compile.h UTS_MACHINE := $(ARCH)
3.3 编译
$ make vexpress_defconfig $ make -j4 $ make LOADADDR=0x60003000 uImage
4.制作根文件系统
4.1 创建rootfs文件夹
$ mkdir rootfs
4.2 解压busybox
$ tar -xvf busybox-1.27.1.tar.bz2 $ cd busybox-1.27.1
4.3 修改Makefile
@@ -161,7 +161,8 @@ export srctree objtree VPATH TOPDIR # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile -CROSS_COMPILE ?= +# CROSS_COMPILE ?= +CROSS_COMPILE ?= arm-linux-gnueabi- # bbox: we may have CONFIG_CROSS_COMPILER_PREFIX in .config, # and it has not been included yet... thus using an awkward syntax. ifeq ($(CROSS_COMPILE),) @@ -187,7 +188,8 @@ SUBARCH := $(shell echo $(SUBARCH) | sed -e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ ) -ARCH ?= $(SUBARCH) +# ARCH ?= $(SUBARCH) +ARCH ?= arm # Architecture as present in compile.h UTS_MACHINE := $(ARCH)
4.4 编译busybox
$ make defconfig $ make menuconfig
做如下修改:
// 勾选编译静态库 Busybox Settings ---> [*] Build static binary (no shared libs)
编译
$ make -j4 $ make install
4.5 创建根文件系统
$ cp -rf busybox-1.27.1/_install/* ./rootfs $ cd ./rootfs/ $ mkdir lib proc tmp dev home etc sys opt mnt $ mkdir -p etc/init.d
4.6 安装modules
$ cd linux-4.4.300 $ make modules_install INSTALL_MOD_PATH=../rootfs
4.7 添加rcS
$ cd rootfs/etc/init.d $ touch rcS $ sudo chmod a+x rcS $ vim rcS
添加如下内容:
1 #!/bin/sh 2 3 PATH=/sbin:/bin:/usr/sbin:/usr/bin 4 runlevel=S 5 prevlevel=N 6 umask 022 7 export PATH runlevel prevlevel 8 # 挂载fstab文件中所有指定的文件系统 9 /bin/mount -a 10 echo /sbin/mdev>/proc/sys/kernel/hotplug 11 # 在/dev目录下建立必须的设备节点 12 mdev -s 13 # 设置主机的名字 14 /bin/hostname -F /etc/sysconfig/HOSTNAME
4.8 添加inittab
rootfs/etc/inittab
添加如下内容:
1 # 设置内核的热插拔,有mdev接收来自内核的消息并做出响应 2 ::sysinit:/etc/init.d/rcS 3 # 在串口启动一个登录会话 4 ::askfirst:-/bin/sh 5 # 作为init重启执行程序 6 ::ctrlaltdel:/sbin/reboot 7 ::restart:/sbin/init 8 # 告诉init在关机时运行umount命令卸载所有文件系统,如果卸载失败,以只读方式重新挂载 9 ::showdown:/bin/mount
4.9 添加fstab
rootfs/etc/fstab
添加如下内容(注意间隔符为Tab):
1 proc /proc proc defaults 0 0 2 sysfs /sys sysfs defaults 0 0 3 tmpfs /tmp tmpfs defaults 0 0
4.10 添加profile
rootfs/etc/profile
添加如下内容:
1 #!/bin/sh 2 3 USER="id -un" 4 LOGNAME=$USER 5 PS1='[root@linux]#' 6 PATH=$PATH 7 HOSTNAME='/bin/hostname' 8 export USER LOGNAME PS1 PATH
4.11 复制动态库
之前有安装gcc-arm-linux-gnueabi,我们把它的库复制到根文件系统。
$ sudo cp -rf /usr/arm-linux-gnueabi/lib/* ./rootfs/lib/
4.12 创建设备节点
$ cd rootfs/dev/ $ sudo mknod -m 664 tty1 c 4 1 $ sudo mknod -m 664 tty2 c 4 2 $ sudo mknod -m 664 tty3 c 4 3 $ sudo mknod -m 664 tty4 c 4 4 $ sudo mknod -m 664 console c 5 1 $ sudo mknod -m 664 null c 1 3
4.13 打包文件系统
$ dd if=/dev/zero of=rootfs.ext4 bs=1M count=32 $ mkfs.ext4 rootfs.ext4 $ sudo mount rootfs.ext4 /mnt/ -o loop $ sudo cp -rf rootfs/* /mnt/ $ sudo umount /mnt/
5. 测试系统
编写启动脚本:
$ touch boot.sh $ chmod a+x boot.sh
修改为如下内容:
1 #!/bin/sh 2 3 qemu-system-arm \ 4 -M vexpress-a9 \ 5 -m 512M \ 6 -kernel linux-4.4.300/arch/arm/boot/zImage \ 7 -dtb linux-4.4.300/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \ 8 -nographic \ 9 -append "root=/dev/mmcblk0 rw console=ttyAMA0" \ 10 -sd rootfs.ext4
执行,如果上面步骤顺利,执行此脚本就可以正常进入系统了。
6.编译bootloader
$ tar -xvf u-boot-2017.05.tar.bz2
6.1 修改Makefile
@@ -246,6 +246,8 @@ ifeq ($(HOSTARCH),$(ARCH)) CROSS_COMPILE ?= endif +CROSS_COMPILE ?= arm-linux-gnueabi- + KCONFIG_CONFIG ?= .config export KCONFIG_CONFIG
6.2 修改config.mk
@@ -22,7 +22,8 @@ OBJCOPYFLAGS := VENDOR := ######################################################################### -ARCH := $(CONFIG_SYS_ARCH:"%"=%) +# ARCH := $(CONFIG_SYS_ARCH:"%"=%) +ARCH := arm CPU := $(CONFIG_SYS_CPU:"%"=%) ifdef CONFIG_SPL_BUILD ifdef CONFIG_TEGRA
6.3 修改vexpress_common.h
u-boot-2017.05/include/configs/vexpress_common.h
做如下修改(注意IP要改为实际值):
@@ -183,9 +183,21 @@ #include <config_distro_defaults.h> /* Basic environment settings */ +/* #define CONFIG_BOOTCOMMAND \ "run distro_bootcmd; " \ "run bootflash; " +*/ + +#define CONFIG_BOOTCOMMAND \ + "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; \ + setenv bootargs 'root=/dev/mmcblk0 rw console=ttyAMA0';\ + bootm 0x60003000 - 0x60500000; " + +#define CONFIG_IPADDR 192.168.103.100 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_SERVERIP 192.168.103.240 + #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 1) \
6.4 配置defconfig
$ make vexpress_ca9x4_defconfig
6.5 编译
$ make -j4
7. 网络配置
7.1 配置tftp
1).安装工具
$ sudo apt install tftp-hpa tftpd-hpa xinetd
2).修改配置文件(Host)
/etc/default/tftpd-hpa
添加如下内容(注意第二行路径改为实际值):
1 TFTP_USERNAME="tftp" 2 TFTP_DIRECTORY="/home/qemulinux/tftpboot" 3 TFTP_ADDRESS="0.0.0.0:69" 4 TFTP_OPTIONS="-l -c -s"
3).创建tftp目录
$ cd /home/qemulinux/ $ mkdir tftpboot $ chmod 777 tftpboot
4).重启tftp服务
$ /etc/init.d/tftpd-hpa restart
5).复制内核和设备树
$ cp linux-4.4.300/arch/arm/boot/uImage ./tftpboot/ $ cp linux-4.4.300/arch/arm/boot/dts/vexpress-v2p-ca9.dtb ./tftpboot/
7.2 配置虚拟桥接网口
1).安装工具
# 虚拟网桥工具 $ sudo apt install bridge-utils # UML(user-mode linux)工具 $ sudo apt install uml-utilities
2).修改interfaces
/etc/network/interfaces
添加如下内容(根据实际网卡名自行修改,ifconfig可查看,这里是enp0s3):
1 auto enp0s3 2 auto br0 3 iface br0 inet dhcp 4 bridge_ports enp0s3
重启计算机,启动后输入:
$ ifconfig
注意:如果产生br0,并且有ip,即可跳过本小结的后面的"3).配置网络"一步。否则,则继续执行。
3).配置网络
# 关闭enp0s3, enp0s3是我主机的无线网口,根据你实际网口修改 $ sudo ifconfig enp0s3 down # 增加一个虚拟网桥br0 $ sudo brctl addbr br0 # 在br0中添加一个接口enp0s3 $ sudo brctl addif br0 enp0s3 # 只有一个网桥,所以关闭生成树协议 $ sudo brctl stp br0 off # 设置br0的转发延迟 $ sudo brctl setfd br0 1 # 设置br0的hello时间 $ sudo brctl sethello br0 1 # 打开br0接口,promisc混杂模式 $ sudo ifconfig br0 0.0.0.0 promisc up # 打开enp0s3接口 $ sudo ifconfig enp0s3 0.0.0.0 promisc up # 从dhcp服务器获得IP地址 $ sudo dhclient br0 # 配置TAP设备 # 创建一个tap0接口,只允许'whoami'(换成实际用户名)访问 $ sudo tunctl -t tap0 -u 'whoami' # 在虚拟网桥中增加一个tap0接口 $ sudo brctl addif br0 tap0 # 打开tap0接口 $ sudo ifconfig tap0 0.0.0.0 promisc up
7.3 启动测试
$ vim boot.sh
添加如下内容:
1 #!/bin/sh 2 3 qemu-system-arm \ 4 -M vexpress-a9 \ 5 -kernel u-boot-2017.05/u-boot \ 6 -nographic \ 7 -m 512M \ 8 -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \ 9 -sd rootfs.ext4
如果一切顺利,此时运行脚本就可以正常使用了。
效果是通过tftp挂在内核和设备树。
8. 配置nfs
1).安装工具
$ sudo apt install portmap nfs-kernel-server nfs-common
2).修改exports文件(host)
/etc/exports
添加如下内容(路径改为实际值):
/home/qemulinux/filesystem *(rw,async,no_root_squash,no_subtree_check)
3).创建nfs文件夹
$ mkdir filesystem $ chmod 777 filesystem
4).复制根文件系统
$ sudo cp -rf ./rootfs/* ./filesystem/
5).重启NFS服务
$ sudo exportfs -a $ sudo /etc/init.d/nfs-kernel-server restart
6).测试nfs服务
# 替换为真实IP $ showmount -e 192.168.xxx.xxx
9. 修改vexpress_common.h
u-boot-2017.05/include/configs/vexpress_common.h
做如下修改(注意,代码中的IP,路径请改为实际值):
@@ -183,9 +183,20 @@ #include <config_distro_defaults.h> /* Basic environment settings */ +/* #define CONFIG_BOOTCOMMAND \ "run distro_bootcmd; " \ "run bootflash; " +*/ + +#define CONFIG_BOOTCOMMAND \ + "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; \ + setenv bootargs 'root=/dev/nfs nfsroot=192.168.103.240:/home/qemulinux/filesystem rw ip=192.168.103.100 init=/linuxrc console=ttyAMA0';\ + bootm 0x60003000 - 0x60500000; " + +#define CONFIG_IPADDR 192.168.103.100 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_SERVERIP 192.168.103.240 #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 1) \
修改后进行编译:
$ make -j4
10. 编写启动脚本
10.1 编写脚本
$ vim boot.sh
修改为如下内容:
1 #!/bin/sh 2 3 qemu-system-arm \ 4 -M vexpress-a9 \ 5 -kernel u-boot-2017.05/u-boot \ 6 -nographic \ 7 -m 512M \ 8 -net nic,vlan=0 -net tap,vlan=0,ifname=tap0
如果一切顺利,此时运行脚本就可以正常使用了。
效果是:启动uboot后,kernel和dtb通过tftp加载,根文件系统通过nfs加载。
10.2 数据文件系统
nfs除了可以挂载根文件系统,还可以挂载数据文件系统:
1).创建文件夹
$ cd /home/qemulinux $ mkdir test $ chmod 777 test
$ cd test
$ echo "hello world" > hello.txt
2).添加访问权限
$ sudo vim /etc/exports
添加如下内容:
/home/qemulinux/test *(rw,async,no_root_squash,no_subtree_check)
重启nfs:
$ /etc/init.d/nfs-kernel-server restart
3).挂载数据文件系统
运行10.1中的脚本,启动qemu版linux系统后,进行挂载:
# 替换真实IP $ mount -o nolock -t nfs 192.168.xxx.xxx:/home/qemulinux/test mnt
此时,我们就可以通过访问开发板linux下的mnt,来访问host主机的test文件夹。