经常会有学习linux的朋友在问学习linux是否一定要买发开版,答案是否定的,但如果你需要在产品级别的验证,买一块开发板做开发板还是非常有必要的。本文主要介绍使用QEMU来调试ARM linux内核,一台PC全部搞定,调试内核非常方便。当然也参考了网上的其他一些资料,这里主要基于的是ARM公司提供的开发板express,通过模拟的方法同样可以达到学习的目的。
1. 准备工作
在ubuntu16.04中安装如下工具:
sudo apt-get install qemu gcc-arm-linux-gnueabi
之后需要下载kernel和busybox的源码包:
Kernel的源码下载网址如下:https://mirrors.edge.kernel.org/pub/linux/kernel/
注:可以根据个人需要选择不同的kernel版本,我选择的是4.16.6
Busybox的源码下载网址如下: https://busybox.net/downloads/
注:本文介绍是以busybox-1.25.1为基础。
2. 编译最小文件系统和kernel
2.1 利用busybox编译最小文件系统
进入busybox代码之后,文件结构如下:
vim Makefile,并在其中添加如下
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabi-
其次, 开始配置busybox, 终端运行make menuconfig
进入menuconfig之后,配置成静态编译。
Busybox Settings --->
Build Options --->
[*] BuildBusyBox as a static binary (no shared libs)
2.2 添加命令结合
最后,运行make install就可以编译busybox了。编译结束之后,在代码的根目录下会生成_install文件夹,该目录是编译好的文件系统需要的一些命令集合。
[email protected]:~/_install$ mkdir etc dev mnt
[email protected]:~/_install$ mkdir -p etc/init.d
在—install /etc/init.d/目录下新创建一个rcS文件,并写入如下内容。
mkdir -p /proc
mkdir -p /tmp
mkdir -p /sys
mkdir 一p/mnt
/bin/mount -a
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev >/proc/sys/kernel/hotplug
mdev –s
在rcS中添加上述内容以后,赋予rcS可执行权限,chmod +x /etc/init.d/rcS.
在_install/etc目录下创建fstab文件,并写入如下内容:
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
debugfs /sys/kernel/debug debugfsdefaults 0 0
在_install/etc目录下创建一个inittab文件,并写入如下内容:
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a –r
在_install/dev目录先创建如下的设备节点,注意需要root权限:
sudo mknod console c 5 1
sudo mknod null c 1 3
最后一步,将busybox中的_install文件夹copy到linux源代码的根目录下即可。
2.3 编译内核
2.3.1配置内核
[email protected]:~$ cdworkspace/linux-4.16.6/
[email protected]:~/workspace/linux-4.16.6$vim Makefile
在打开的Makefile文件中做如下修改:
-ARCH ?= $(SUBARCH)
-CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
+ARCH ?= arm
+CROSS_COMPILE ?= arm-linux-gnueabi-
[email protected]:~/workspace/linux-4.16.6$make vexpress_defconfig
配置initramfs,在initramfs source file中填入_install,同时把Default kernel command string清空,如下所示:
General setup --->
[*] InitialRAM filesystem and RAM disk (initramfs/initrd) support
(_install)Initramfs source file(s)
Boot options -->
()Default kernel command string
配置memory split为“3G/1G user/kernel split”, 并打开高端内存。
Kernel Features --->
Memory split: (3G/1G user/kernelsplit:)
[*] High Memory Support
2.3.2 编译内核
[email protected]:~/workspace/linux-4.16.6$make bzImage -j8
[email protected]:~/workspace/linux-4.16.6$make dtbs
到此关于配置kernel, busybox全部完成,接下就是运行qemu模拟ARM了。
3. 运行qemu模拟ARM
Vexpress是基于4核的Cortex-A9的开发平台,就下来就是运行qemu的命令:
[email protected]:~/workspace/linux-4.16.6$qemu-system-arm -M vexpress-a9 -smp 4 -m 1024M -kernel arch/arm/boot/zImage-append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtbarch/arm/boot/dts/vexpress-v2p-ca9.dtb –nographic
这个地方也是很明确了,-M制定了vexpress-a9,smp(对称multiprocessor)为4核,-m制定只用的1G内存.
用过的朋友会发现进入调试窗口之后,就无法在本终端中通过命令退出来了。我们可以重新打开一个终端,输入如下命令就可以关闭qemu模拟环境了。
[email protected]:~$ killallqemu-system-arm
4 qemu调试linux内核
4.1 安装armgdb调试工具
[email protected]:~$ sudo apt-getinstall gdb-arm-none-eabi
如果确定要用gdb去调试内核,在步骤2.3.1配置内核的编译选项是,需要打开
Kernel hacking --->
Compile-time checks and compileroptions 一一->
[*] Compile the kernel with debuginfo
之后在终端输入:
[email protected]:~/workspace/linux-4.16.6$qemu-system-arm -nographic -M vexpress-a9 -m 1024M -kernel arch/arm/boot/zImage -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtbarch/arm/ boot/dts/vexpress-v2p-ca9.dtb -S –s
(*)-S:表示QEMU虚拟机会冻结CPU,直到远程的GDB输入相应控制命令。
(*)-s:表示在1234端口接受GDB的调试连接。
之后,我们重新打开一个终端,输入如下命令
[email protected]:~/workspace/linux-4.16.6$arm-none-eabi-gdb --tui vmlinux
在gdb命令行中,输入如下命令
(gdb) target remote localhost:1234
(gdb) b start_kernel
(gdb) c
由此,便可以通过gdb的命令行来调试kernel了,正如上述命令,在start_kernel中设置了一个断点,界面如下: