Linux驱动开发过程中,段错误和oops就是家常便饭,直接在本机上电脑会吃不消。以前都是找一个嵌入式开发板,用编译-下载-调试这样的方法。
也尝试过Virtualbox。VirtualBox内核安装比较麻烦,如果不是在虚拟机上开发,就要把代码目录共享上去,过程繁琐,还不如用开发板。
最近尝试了Qemu。qemu的配置要复杂一些,很多问题搞起来比较伤脑筋。不过一旦把配置搞定了,调试效率远超开发板和virtualbox。
这里对qemu的配置做个记录。
1. 编译内核
内核需要事先编译出来,这里展示的是通用的内核编译方法。
内核目录下选择通用配置文件:
cp arch/x86/configs/x86_64_defconfig .config
调整内核配置文件适配当前内核版本:
make menuconfig
编译内核文件:
make bzImage
2. 生成根文件系统
这一步是最重要的,生成一个调试环境的文件系统。这里介绍四种方法。
2.1 制作busybox根文件系统 (方法一)
busybox是一个轻量级的工具集合,包含了init和大部分常用的Linux工具。官网:https://busybox.net 。
这个方法编译出来的根文件系统是最小的,起动速度也是最快的。就是自带工具可能比较少,有些东西需要自己编译。
2.1.1 创建镜像文件
创建raw格式的镜像文件:
qemu-img create -f raw disk.raw 512M
mkfs -t ext4 ./disk.raw
把raw文件挂载到临时目录:
sudo mount -o loop ./disk.raw ./img
2.1.2 安装模块
进入内核目录,把内核里的模块安装进文件系统:
sudo make modules_install \ # 安装内核模块
INSTALL_MOD_PATH=./img # 指定安装路径
2.1.3 busybox
下载busybox的源码,编译之前需要配置。busybox的配置方式和内核类似:
cd busybox
make defconfig
make menuconfig
调整其中以下选项,编译包含静态库:
Busybox Settings --->
--- Build Options
[*] Build BusyBox as a static binary (no shared libs)
然后编译busybox,这里的path_to_disk_img_mount_point就是刚才raw文件挂载的临时目录:
make CONFIG_PREFIX= install
2.1.4 创建系统文件
配置init环境:
根目录下手工创建etc/init.d, dev, proc, sys 这三个目录。
/etc/inittab:
::sysinit:/etc/init.d/rcS
::askfirst:/bin/ash
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init
/etc/init.d/rcS:
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
并把/etc/init.d/rcS改为可执行文件。
2.1.5 内核启动脚本
正常启动内核:
qemu-system-x86_64 \
-m 512 \
-kernel ../kernel/arch/x86_64/boot/bzImage \
-drive format=raw,file=./disk.raw \
-append "init=/linuxrc root=/dev/sda rw"
查看内核串口输出:
qemu-system-x86_64 \
-m 512 \
-kernel ../kernel/arch/x86_64/boot/bzImage \
-drive format=raw,file=./disk.raw \
-append "init=/linuxrc root=/dev/sda rw console=ttyS0" \
-serial file:./serial.out
2.2 用ISO文件制作debian文件系统 (方法二)
这个方法类似于虚拟机安装系统,利用系统自带的安装引导程序生成文件系统。这样安装出来的是一个完整的debian,可以用apt安装工具。
2.2.1 生成镜像文件
生成raw镜像文件:
qemu-img create -f raw debiam-10G.img 10G
安装debian:
qemu-system-x86_64 -m 512 -boot d -hda ./debiam-10G.img -cdrom iso/debian-9.4.0-amd64-netinst.iso
2.2.2 内核启动脚本
qemu-system-x86_64 -m 512 -boot c -kernel ../kernel/arch/x86_64/boot/bzImage -append root=/dev/sda1 -hda ./debiam-10G.img -hdb ./fat.img -net nic -net user,hostfwd=tcp::10022-:22
2.3 用debootstrap制作Debian根文件系统 (方法三)
这方法是利用debian官方的debootstrap,把debian装在本机的一个目录里。这个系统也是完整的debian。
2.3.1 生成镜像文件
生成raw镜像文件:
qemu-img create -f raw debiam-10G.img 10G
挂载文件系统:
sudo mount -o loop ./debiam-10G.img ./img
2.3.2 安装debian
安装debian,这里的path_to_disk_img_mount_point就是刚才镜像文件的挂载点:
sudo debootstrap --arch amd64 stretch
2.3.3 配置网络
这里的网络是主机和虚拟机之间的网络。
让系统启动时自动运行dhclient:
$ cat > /etc/systemd/network/eth.network <<__END__
[Match]
Name=eth0
[Network]
DHCP=yes
__END__
$ systemctl enable systemd-networkd
$ systemctl start systemd-networkd
脚本里的网络设备名设置为eth0。不同的设备可能不一样,比如有些电脑会叫enp0s3。具体网卡名称可以通过ip link查看。
2.3.4 内核启动脚本
qemu-system-x86_64 \
-m 512 \
-kernel ../../kernel/arch/x86_64/boot/bzImage \
-drive format=raw,file=./debian-stretch-x86_64.img,index=0 \
-drive format=raw,file=./../fat/fat.winxp.img,index=1 \
--append "console=ttyS0 root=/dev/sda rw" \
-enable-kvm \
-nographic \
-device e1000,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::5555-:22
系统启动后,在本机上可以用ssh -p 5555 localhost远程登录虚拟机。
2.4 使用Fedora cloud image (方法四)
Fedora官方有相应的的镜像,叫cloud image,可以直接下载:https://alt.fedoraproject.org/
3 虚拟机访问公网
qemu的网络配置是一个比较纠结的问题,这里用桥接的方式,只能用有线网卡,不支持无线网卡。
没什么技巧可言,直接用脚本启动桥接,系统中途会断网片刻:
#!/bin/bash
ETH_DEV=enp3s0
USERNAME=myname
brctl addbr br0
ip addr flush dev ${ETH_DEV}
brctl addif br0 ${ETH_DEV}
tunctl -t tap0 -u ${USERNAME}
brctl addif br0 tap0
ip link set ${ETH_DEV} up
ip link set tap0 up
ip link set br0 up
brctl show
dhclient -v br0
与此同时,kernel的启动脚本也要有所改变,这里以debian镜像为例:
qemu-system-x86_64 \
-m 512 \
-enable-kvm \
-kernel ../../kernel/arch/x86_64/boot/bzImage \
-drive format=raw,file=./debian-stretch-x86_64.img,index=0 \
--append "root=/dev/sda rw" \
-device e1000,netdev=network0 \
-netdev tap,id=network0,ifname=tap0,script=no,downscript=no
Reference:
使用 qemu 搭建内核开发环境 . https://www.cnblogs.com/hellogc/p/7482066.html
Creating a Minimal Kernel Development Setup using KVM/Qemu . https://saurorja.org/2011/07/04/creating-a-minimal-kernel-development-setup-using-kvmqemu/
Creating a minimal kernel development setup using QEMU and Archlinux . https://medium.com/@clem.boin/creating-a-minimal-kernel-development-setup-using-qemu-and-archlinux-987896954d84
Setting up QEMU-KVM for kernel development . https://www.collabora.com/news-and-blog/blog/2017/01/16/setting-up-qemu-kvm-for-kernel-development/
Switching to systemd-networkd . https://www.joachim-breitner.de/blog/664-Switching_to_systemd-networkd
Qemu Documentation/Networking . https://wiki.qemu.org/Documentation/Networking
Archlinux QEMU . https://wiki.archlinux.org/index.php/QEMU