1. 环境及需求

  1. host主机
    • 系统:ubuntu 16.04 x86_64
    • CPU:双核i5
    • 内存:8G
    • 硬盘:1T
  2. guest虚拟机
    • CPU::cortex-a53, arm64位 四核
    • 内存:1G
    • 内核:kernel-4.9.140
    • 硬件:六个网口,其中一个桥接到host主机的一个物理网口
    • 硬盘:文件系统,32G, 可持久化

2. 安装QEMU

1. 从仓库安装

sudo apt-get install qemu-system-aarch64

2. 从源码安装

  1. 源码获取:https://download.qemu.org/
  2. 解压:
tar -xvf qemu-5.1.0.tar.xz
  1. 配置:
./configure --enable-kvm --enable-virtfs --enable-vhost-net --enable-vhost-kernel --enable-vhost-user --enable-vdi --enable-parallels --enable-linux-user --enable-user --enable-system --enable-guest-agent --enable-curses --enable-vnc --enable-fdt --enable-linux-aio --enable-libnfs --enable-slirp

如果出现错误,根据提示apt安装对应的包即可
4. 编译 & 安装:

make
sudo make install

3. 配置内核

  1. 获取内核
    https://mirrors.edge.kernel.org/pub/linux/kernel/
  2. 配置内核
    内核需支持以下配置:
CONFIG_PCI=y
CONFIG_VIRTIO_PCI=y
CONFIG_PCI_HOST_GENERIC=y

编译内核镜像:

make zImage
  • 编译出的内核位于arch/arm64/boot/zImage

4. 制作文件系统

  1. 下载buildroot
    https://buildroot.org/download.html
  2. 配置buildroot生成tar和ramdisk镜像
Filesystem images --->
    [*] cpio the root filesystem (for use as an initial RAM filesystem) 
    [*] tar the root filesystem #配置默认串口 qemu默认串口名称为ttyAMA0
System configuration >
    Run a getty (login prompt) after boot 
        (ttyAMA0) TTY port
  1. 编译
make
  • 在output/images下生成rootfs.cpio.gz和rootfs.tar文件

5. 创建虚拟硬盘

1. 在host主机上制作

  1. 创建空的虚拟硬盘
qemu-img create -f vdi rootfs.vdi 32G
  • -f:指定虚拟硬盘格式
  1. 挂载虚拟硬盘到host主机
#host主机安装nbd内核模块
sudo modprobe nbd
  1. 挂载虚拟硬盘
sudo qemu-nbd -c /dev/nbd0 rootfs.vdi
  1. 虚拟硬盘分区
sudo fdisk /dev/nbd0
  1. 格式化分区
sudo mkfs.ext4 /dev/nbd0p1
  1. 挂载虚拟硬盘
sudo mount /dev/nbd0p1 /mnt
  1. 解压出文件系统到虚拟硬盘
sudo tar -xvf rootfs.tar -C /mnt
  1. 卸载虚拟硬盘
sudo umount /mnt
  1. 断开VDI虚拟硬盘连接
sudo qemu-nbd -d /dev/nbd0

2. 挂载到VirtualBox虚拟机里面制作

参考VirtualBox虚拟机虚拟硬盘操作。

6. 创建host桥接网络

主机上有一个物理网口,需要将此网口和虚拟机网口桥接在一起。如果host主机为虚拟机,则需要打开网卡的混杂模式

enp0s3    Link encap:Ethernet  HWaddr 08:00:27:1f:8d:c8  
          inet6 addr: fe80::a00:27ff:fe1f:8dc8/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:54 errors:0 dropped:0 overruns:0 frame:0
          TX packets:90 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:5917 (5.9 KB)  TX bytes:12560 (12.5 KB)</pre>
  1. 创建网桥
sudo brctl addbr br0
  • qemu虚拟机默认连接到br0网桥.
  1. 添加端口到网桥
sudo brctl addif enp0s3
  1. 清除网口IP,给网桥添加IP
sudo ip addr flush enp0s3
sudo ifconfig br0 192.168.10.2
  1. 配置qemu网桥规则
    1. 如:允许br0桥接,则:
sudo mkdir -p /etc/qemu
sudo sh -c 'echo "allow br0" > /etc/qemu/bridge.conf'
2. 允许所有的网桥:
echo "allow all" | sudo tee /etc/qemu/bridge.conf
  1. 设置文件权限
sudo chmod 644 /etc/qemu/bridge.conf
sudo chmod u+s /usr/lib/qemu/qemu-bridge-helper

所有操作可以添加到开机启动脚本rc.local里面,实现自动添加网桥。

#rc.local
brctl addbr br0
brctl addif br0 enp0s3
ifconfig enp0s3 up

在interfaces里面添加br0的IP信息:

auto br0
iface br0 inet static
    address 192.168.10.2
    netmask 255.255.255.0

打开host主机的地址转发功能,关闭防火墙:

sudo ufw disable
sudo vim /etc/sysctl.conf
#取消注释
net.ipv4.ip_forward=1

重启host主机生效

7. 启动qemu虚拟机

启动时需要切换到root用户运行,因为需要创建host虚拟网卡。

1. 正常启动

启动命令:

qemu-system-aarch64  -m 1G -cpu cortex-a53 -smp 4 -machine virt,highmem=off \
                    -kernel zImage \
                    -append "root=/dev/vda1 rw rootfstype=ext4 rootflags=data=journal console=ttyAMA0 rootwait earyprintk" \
                    -drive file=rootfs.vdi,cache=none,if=virtio,format=vdi \
                    -serial tcp::4446,server,telnet,nowait \
                    -monitor tcp::4447,server,telnet,nowait \
                    -device virtio-net-pci,netdev=net0         \
                    -netdev bridge,id=net0,br=br0  \
                    -device virtio-net-pci,netdev=net1         \
                    -netdev user,id=net1  \
                    -device virtio-net-pci,netdev=net2         \
                    -netdev user,id=net2  \
                    -device virtio-net-pci,netdev=net3         \
                    -netdev user,id=net3  \
                    -device virtio-net-pci,netdev=net4         \
                    -netdev user,id=net4  \
                    -device virtio-net-pci,netdev=net5         \
                    -netdev user,id=net5  \
                    -device virtio-net-pci,netdev=net6         \
                    -netdev user,id=net6  \
                    -nographic
  • -m:指定内存大小,1G
  • -cpu:指定CPU型号,cortex-a53
  • -smp:指定内核数,4
  • -machine:指定模拟机器型号,virt: arm通用虚拟机。可以通过qemu-system-aarch64 -machine help查看支持的所有虚拟机型号。
  • -kernel:内核镜像文件,Image
  • -append:指定内核启动参数
    • /dev/vda1:挂载的虚拟硬盘在内核里面的名称默认为vda。可以通过ramdisk方式启动系统,查看虚拟硬盘在内核中的默认名称。
    • ttyAMA0:qemu启动后,内核里面默认的串口名称
  • -drive:指定虚拟硬盘,用于挂载文件系统
  • -serial:指定默认串口
    • -stdio: host的标准输出
    • tcp::4446,server,telnet : 通过host主机的telnet端口4446输出
    • nowait:不指定时,则默认当通过telnet登录时,虚拟机才启动。
  • -monitor:指定监控设备,同-serial
  • -device virtio-net-pci:添加虚拟设备,虚拟网卡。qemu-system-aarch64 -device help`可以查看所有可模拟的设备类型。
  • -netdev:指定网卡设备的名称,不是内核里面显示的名称,只是一个ID,和-netdev配合使用,用于区分网卡类型。
  • -netdev:指定网卡类型
    • bridge:桥接类型
    • id:绑定一个-device虚拟网卡设备的ID
    • br:桥接的host主机的网桥名称,默认为br0
  • -nographic:指明没有显示设备

2. ramdisk启动

qemu-system-aarch64  -m 1G -cpu cortex-a53 -smp 4 -machine virt,highmem=off \
                    -kernel zImage \
                    -initrd rootfs.cpio.gz
                    -append "root=/dev/ram0 rw rootfstype=ext4 rootflags=data=journal console=ttyAMA0 rootwait earyprintk" \
                    -drive file=rootfs.vdi,cache=none,if=virtio,format=vdi \
                    -serial tcp::4446,server,telnet,nowait \
                    -monitor tcp::4447,server,telnet,nowait \
                    -device virtio-net-pci,netdev=net0         \
                    -netdev bridge,id=net0,br=br0  \
                    -device virtio-net-pci,netdev=net1         \
                    -netdev user,id=net1  \
                    -device virtio-net-pci,netdev=net2         \
                    -netdev user,id=net2  \
                    -device virtio-net-pci,netdev=net3         \
                    -netdev user,id=net3  \
                    -device virtio-net-pci,netdev=net4         \
                    -netdev user,id=net4  \
                    -device virtio-net-pci,netdev=net5         \
                    -netdev user,id=net5  \
                    -device virtio-net-pci,netdev=net6         \
                    -netdev user,id=net6  \
                    -nographic
  • -initrd:指定ramdisk镜像文件
  • -append:指定内核启动参数
    • /dev/ram0:内核中默认ramdisk设备名称

Related Posts