构建嵌入式qemu
编译安装qemu
为了避免一些依赖兼容性的问题,我用一个新建的ubuntu18.04做容器。
首先从github上下载qemu。
1 | git clone https://github.com/qemu/qemu.git |
在安装前需要装一些依赖:
1 | sudo apt-get install build-essential zlib1g-dev pkg-config libglib2.0-dev binutils-dev libboost-all-dev autoconf libtool libssl-dev libpixman-1-dev libpython-dev python-pip python-capstone virtualenv bison flex |
编译时的配置信息如下(选了一大堆架构列表,把qemu装在/opt/qemu中):
1 | ./configure --target-list=arm-softmmu,mips-softmmu,mips64-softmmu,mips64el-softmmu,mipsel-softmmu,aarch64-softmmu,arm-linux-user,aarch64-linux-user,mips64el-linux-user,mipsel-linux-user,mips-linux-user,mips64-linux-user --prefix=/opt/qemu --python=/usr/bin/python2.7 |
然后make && sudo make install
一把梭。
安装系统
首先我们需要从网上下载kernel和initrd。去镜像站就可以下载到,比如(我这里用的ubuntu的来安装):
1 | https://mirrors.tuna.tsinghua.edu.cn/debian/dists/buster/main/installer-armhf/current/images/netboot/ |
或者
1 | wget -r -nH -nd -np -R "index.html*" --quiet http://ports.ubuntu.com/ubuntu-ports/dists/xenial/main/installer-armhf/current/images/generic-lpae/netboot/ |
我这里用的是第二个。
创建一个空的filesystem:
1 | qemu-img create -f qcow2 ubuntu.img 16G |
现在我们拿到了kernel、initrd和新的硬盘镜像了,然后需要在qemu里面安装系统了,我的安装方法如下,记得append时要把filesystem的地址改成ram,原因是要把驱动安装程序放在内存中运行,kernel和initrd指定之前下载好的就好(注意内存设置的不要比虚拟机大否则会崩掉):
1 | sudo /opt/qemu/bin/qemu-system-arm -m 1024 -M virt -cpu cortex-a15 -smp cpus=4,maxcpus=4 -kernel ./vmlinuz -initrd ./initrd.gz -append "root=/dev/ram" -drive file=../ubuntu.img,if=none,format=qcow2,id=hd0 -device virtio-blk-device,drive=hd0 -netdev type=tap,id=net0 -device virtio-net-device,netdev=net0,mac=52:54:00:fa:ee:10 -nographic |
在安装时,会遇到需要网络的情况(安装一半会卡住),我们需要手动配置一下网络,这里我们看到我们的网卡名字是enp0s25(这个改成自己的),qemu运行后开启的网卡名字叫tap0,我们配置一下tap0的iptables,并设置好ip。这里注意一下需要先启动qemu,我们修改qemu创建的接口(tap0),如果我们自己创建一个tap0的话qemu运行时不会直接使用这个tap0,会重新创建一个tap1:
1 | sudo sysctl -w net.ipv4.ip_forward=1 |
运行这些命令后qemu里面才能上网
然后在qemu的安装界面,我们配置一下固定的IP,就是脚本里面改的IP(任意一个C段网都行,不要和宿主机的网段一样就好,这里配成了192.168.100.2)。网关填写tap0的地址,DNS设置自己的DNS,如果不知道就设置成8.8.8.8或114.114.114.114。
安装要过很久,建议晚上睡前安,第二天收割img。
安装好了后会有提示系统没法boot,这是正常的,毕竟我们没有grub,直接退出安装就好了。
启动安装好的系统
由于我们没有grub帮助我们boot,所以我门需要把initrd从qcow2中提取出来,单独指定给qemu。这是我们需要一个工具libguestfs-tools
。apt一把梭。
1 | sudo apt-get install libguestfs-tools -yf |
用virt-ls看一下initrd的文件名(别问我问啥要加这两个环境变量,log提示我加的):
1 | LIBGUESTFS_DEBUG=1 LIBGUESTFS_TRACE=1 sudo virt-ls ubuntu.img /boot/ |
然后把initrd copy出来
1 | LIBGUESTFS_DEBUG=1 LIBGUESTFS_TRACE=1 sudo virt-copy-out -a ubuntu.img /boot/initrd.img-4.4.0-135-generic-lpae ./ |
后面我们就用拷贝出来的initrd,安装好的filesystem——ubunut.img,以及kernel将ubuntu运行起来。
1 | sudo /opt/qemu/bin/qemu-system-arm -m 1024 -M virt -cpu cortex-a15 -smp cpus=4,maxcpus=4 -kernel ./vmlinuz -initrd ./initrd.img-4.4.0-135-generic-lpae -append "root=/dev/vda2" -drive file=./ubuntu.img,if=none,format=qcow2,id=hd0 -device virtio-blk-device,drive=hd0 -netdev type=tap,id=net0 -device virtio-net-device,netdev=net0,mac=52:54:00:fa:ee:10 -nographic |
这里把root改成/dev/vda2,从硬盘中得到filesystem。运行后我们还是需要修改一下tap0的iptables和网络配置(nat映射神马的,这样外网可以访问):
1 |
|
到这里我们的嵌入式虚拟环境就搭建好了。