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文件夹。

posted @ 2023-03-25 16:36  this毛豆  阅读(525)  评论(0编辑  收藏  举报