第四期 QEMU调试Linux内核实验 《虚拟机就是开发板》

本文介绍如何从零开始构建一个可以在虚拟开发板上运行的Linux最小系统。主要分为三步:编译内核、制作根文件系统及调试运行。通过详细步骤指导读者完成整个过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        这一期我们来制作一个Linux的最小系统,让它在虚拟开发板上运行。整体的流程类似于LFS( http://www.linuxfromscratch.org/),不过LFS的目标是制作一个功能较完善的Linux发行版,而我们要做的是一个最小系统,步骤会精简很多,大体就分成三个步骤:1.编译内核;2.制作根文件系统;3.调试运行。 

        第一步:编译内核

        1. 首先安装交叉编译器,执行: sudo apt-get install gcc-arm-linux-gnueabi
        2. 下载内核源文件 https://www.kernel.org/pub/linux/kernel/ ,我这里下载的是 4.1.38 版本,一个比较稳定的版本;
        3.解压内核  tar zvxf linux-4.1.38.tar.gz -C xxxx  (xxxx为需要解压的目录)
        4. 进入kernel 源文件目录,然后执行:
                export ARCH=arm 
                export CROSS_COMPILE=arm-linux-gnueabi-
                make vexpress_defconfig
                make zImage
                make modules
                make dtbs
                编译后生成 在 arch/arm/boot 目录下生成 zImage 文件,则说明编译成功。

        第二步:制作根文件系统

        1.制作根文件系统首先要生成一个虚拟磁盘,创建一个虚拟磁盘的两种方法:
                dd if=/dev/zero of=vexpress.img bs=512 count=$((2*1024*100))
                qemu-img create -f raw vexpress.img 100M
        这两种方法任选一种执行就可以,目的就是生成一个vexpress.img的虚拟镜像文件,为了更好的兼容性选择 raw 格式的镜像。
        2.虚拟磁盘中创建分区并修改:
                (1). fdisk vexpress.img ,然后使用n命令创建分区,各种下一步就行;
                (2). losetup /dev/loop0 vexpress.img ,挂载vexpress.img到/dev/loop0设备上;
                (3). partx -u /dev/loop0 ,使用partx命令让系统刷新系统的分区信息;
                (4). mkfs.ext2 /dev/loop0p1 ,制作ext2格式的文件系统;
                (5). mkdir rootfs ,建立一个rootfs目录用来作为挂载目录,
                      mount -o loop /dev/loop0p1 ./rootfs ,将生成的ext2格式的分区挂载到rootfs目录;
                (6). 执行到这里虚拟磁盘就已经制作好了,下面的两个步骤是卸载磁盘时的操作,可以先跳过,直接到第三节去编译 busybox;
                (7). partx -d /dev/loop0 ,卸载loop0设备下的分区; 如果执行不成功可以试试  sudo umount -f rootfs
                (8). losetup -d /dev/loop0 ,卸载loop0设备;
                说明:
                如果直接使用 mkfs.ext3 写入img文件,无法使用fdisk显示分区信息;
                fdisk n命令 默认的first sector 是2048扇区;默认分区名为 文件名+分区序号;
                mount 挂载空分区会报错 wrong fs type, bad option, bad superblock;
                losetup /dev/loop0 vexpress.img 命令相当于mount命令中的 -o loop 参数;
                partx -u /dev/loop0  强制内核刷新可识别分区;
                查看分区类型  df -Th;
        3.编译 Busybox:
                (1). 下载Busybox https://busybox.net/downloads/ ,我下载的版本是 1.26.2 ,一个比较稳定的版本;
                (2). 解压内核  tar jvxf busybox-1.26.2.tar.bz2 -C xxxx  (xxx为需要解压的目录)
                (3). 进入 Busybox 源文件目录下执行 make menuconfig
                        做如下配置:
                        Busybox Settings  --->
                            Build Options  --->
                                [*] Build BusyBox as a static binary (no shared libs)
                                (arm-linux-gnueabi-) Cross Compiler prefix
                        使用交叉编译器编译Busybox
                (4). 执行 make 编译Busybox
                (5). 执行 make install 会在 _install 目录下生成 需要的文件 bin linuxrc sbin usr  ;
        4.制作根文件系统:
                (1). 拷贝busybox
                        sudo cp -raf busybox/_install/*  rootfs/
                (2). 拷贝运行库
                        sudo cp -arf /usr/arm-linux-gnueabi/lib rootfs/
                        sudo rm rootfs/lib/*.a
                        sudo arm-linux-gnueabi-strip rootfs/lib/*
                (3). 创建必要目录
                        sudo mkdir -p rootfs/proc/
                        sudo mkdir -p rootfs/sys/
                        sudo mkdir -p rootfs/tmp/
                        sudo mkdir -p rootfs/root/
                        sudo mkdir -p rootfs/var/
                        sudo mkdir -p rootfs/mnt/
                (4). 创建必要节点
                        sudo mkdir -p rootfs/dev/
                        sudo mknod rootfs/dev/tty1 c 4 1
                        sudo mknod rootfs/dev/tty2 c 4 2
                        sudo mknod rootfs/dev/tty3 c 4 3
                        sudo mknod rootfs/dev/tty4 c 4 4
                        sudo mknod rootfs/dev/console c 5 1
                        sudo mknod rootfs/dev/null c 1 3
                (5). 制作必要etc文件
                        etc 目录下的必要文件有5个:fstab,init.d/rcS,inittab,profile,sysconfig/HOSTNAME
                        我把这五个文件放到 https://github.com/aggresss/LKDemo 中 tools 目录下的 etc.tar.gz 里,可以下载并解压后使用;
                        sudo cp -arf etc rootfs/
        到这里根文件系统就已制作完成,退出rootfs目录并执行 losetup -d /dev/loop0 卸载虚拟磁盘文件。

        第三步:调试运行

        1. 启动Linux最小系统需要我们刚才生成的3个文件:
                (1). Linux kernel目录下 arch/arm/boot/dts/vexpress-v2p-ca9.dtb  文件;
                (2). Linux kernel目录下 arch/arm/boot/zImage 文件
                (3). 生成的虚拟磁盘文件: vexpress.img;
        将这三个文件放到同一个目录下。
        2. 制作启动脚本:
                在上面三个文件的同目录下创建启动脚本 vim run_linux.sh
                qemu-system-arm \
                    -nographic \
                    -sd vexpress.img \
                    -M vexpress-a9 \
                    -m 512M \
                    -kernel zImage \
                    -dtb vexpress-v2p-ca9.dtb \
                    -smp 4 \
                    -append "init=/linuxrc root=/dev/mmcblk0p1 rw rootwait earlyprintk console=ttyAMA0"
                增加可执行权限 chmod +x run_linux.sh
        3. 调试运行:

                执行 ./run_linux.sh,即可在模拟的开发板上运行Linux系统,下面是运行后的截图:

                

        4. 关闭模拟开发板进程:

                将下面的命令做成脚本运行便可以彻底关闭已经运行的QEMU进程:
                ps -A | grep qemu-system-arm | awk '{print $1}' | xargs sudo kill -9

<think>好的,用户现在想了解如何编译Linux内核5.9.6版本,并用QEMU模拟ARM开发板进行驱动开发学习。我需要先回顾之前的对话历史,看看有没有相关信息可以参考。之前用户问过关于内核配置中修改ARM架构兼容性的问题,所以可能已经有一定的背景知识,比如配置内核选项、交叉编译工具链的使用等。 首先,用户的目标是编译特定版本的内核,然后使用QEMU模拟ARM环境进行驱动开发。这需要确保内核版本5.9.6的源码可用,并且QEMU支持对应的ARM开发板模拟。可能需要检查该内核版本是否兼容QEMU的某些板子,比如vexpress-a9或versatilepb,这些都是常用的模拟板。 接下来,我需要考虑用户可能的背景。用户可能刚开始学习内核驱动开发,对交叉编译、QEMU的使用还不熟悉。因此,步骤需要详细,特别是环境搭建部分,比如安装依赖包、交叉编译工具链、QEMU本身等。同时,用户可能需要知道如何获取正确版本的内核源码,可能需要使用wget或者git,但5.9.6是一个较旧的版本,可能需要从kernel.org的存档下载。 然后,配置内核时,用户需要指定ARCH=arm,使用交叉编译工具链。这里可能需要提醒用户安装正确的工具链,比如gcc-arm-linux-gnueabihf。此外,在menuconfig中,确保配置支持对应的ARM板,可能需要选择对应的SOC类型,比如vexpress,同时启用必要的驱动和模块支持,比如网络驱动、文件系统支持等,方便后续测试。 编译完成后,用户需要生成zImage和dtb文件,用于QEMU启动。同时,创建根文件系统,用户可能不熟悉如何制作initramfs或者使用busybox,所以需要详细说明步骤,或者提供替代方法,比如使用预先构建的文件系统镜像。 在QEMU启动命令中,需要指定正确的机器类型、内核镜像、设备树文件、内存大小,以及根文件系统的位置。如果用户需要网络支持,可能还需要配置虚拟网络设备,比如tap设备,并启用网络驱动。 驱动开发部分,用户可能需要一个简单的示例,比如字符设备驱动,包括编写代码、Makefile,以及测试步骤。需要确保编译驱动时使用正确的内核源码路径和架构。测试时,通过insmod加载模块,查看输出,可能需要QEMU的控制台或者串口输出来调试。 潜在的问题可能包括内核版本过旧导致的依赖问题,工具链不兼容,QEMU启动参数错误,根文件系统无法挂载等。需要提醒用户注意版本匹配,检查错误日志,逐步验证每个步骤。 用户可能没有提到的深层需求是希望有一个可重复、隔离的环境进行驱动开发,避免影响宿主机系统。因此,使用QEMU模拟是非常合适的,但需要确保整个流程清晰,用户能够顺利启动模拟环境并进行测试。 总结来说,回答需要分步骤详细说明环境搭建、内核编译、QEMU配置、根文件系统准备、驱动编写和测试,同时提供常见问题的解决方法,确保用户能够一步步完成操作,并理解每个步骤的作用。</think>以下是编译 Linux 5.9.6 内核并使用 QEMU 模拟 ARM 开发板进行驱动开发学习的完整流程: --- ### **1. 环境准备** #### **1.1 安装依赖** ```bash # Ubuntu/Debian 系统 sudo apt update sudo apt install -y git build-essential gcc-arm-linux-gnueabihf qemu-system-arm libssl-dev bison flex libncurses-dev ``` #### **1.2 获取内核源码** ```bash wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.9.6.tar.xz tar -xvf linux-5.9.6.tar.xz cd linux-5.9.6 ``` --- ### **2. 配置内核** #### **2.1 选择默认配置** 使用 `vexpress_defconfig`(QEMU 支持的 ARM 开发板): ```bash make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- vexpress_defconfig ``` #### **2.2 可选:自定义配置** 启动图形化配置界面: ```bash make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig ``` **关键配置项**: - **启用模块支持**:确保 `Enable loadable module support` 已开启。 - **调试支持**:在 `Kernel Hacking` 中启用 `Kernel debugging` 和 `Compile the kernel with debug info`。 - **驱动支持**:根据需要启用串口、网络、块设备等驱动(默认 `vexpress_defconfig` 已包含基础支持)。 --- ### **3. 编译内核** ```bash make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-j$(nproc) ``` 编译完成后生成文件: - **内核镜像**:`arch/arm/boot/zImage` - **设备树文件**:`arch/arm/boot/dts/vexpress-v2p-ca9.dtb` --- ### **4. 创建根文件系统** #### **4.1 使用 BusyBox 构建最小文件系统** ```bash # 下载并编译 BusyBox wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2 tar -xvf busybox-1.36.1.tar.bz2 cd busybox-1.36.1 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig # 可选:启用静态链接 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-j$(nproc) make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- install ``` #### **4.2 创建 initramfs** ```bash # 创建根文件系统目录 mkdir -p rootfs/{dev,proc,sys,bin} sudo mknod rootfs/dev/console c 5 1 sudo mknod rootfs/dev/null c 1 3 # 复制 BusyBox 文件 cp -r busybox-1.36.1/_install/* rootfs/ # 创建初始化脚本 echo '#!/bin/sh mount -t proc none /proc mount -t sysfs none /sys /sbin/mdev -s exec /bin/sh' > rootfs/init chmod +x rootfs/init # 打包为 initramfs cd rootfs find . | cpio -o -H newc | gzip > ../initramfs.cpio.gz ``` -- ### **5. 启动 QEMU** ```bash qemu-system-M vexpress-a9 \ -m 512M \ -kernel linux-5.9.6/arch/arm/boot/zImage \ -dtb linux-5.9.6/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \ -append "console=ttyAMA0 root=/dev/ram rdinit=/init" \ -initrd initramfs.cpio.gz \ -nographic \ -net nic -net user,hostfwd=tcp::2222-:22 # 可选:启用网络 ``` --- ### **6. 驱动开发示例(字符设备驱动)** #### **6.1 编写驱动代码 `hello.c`** ```c #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #define DEVICE_NAME "hello" static int __init hello_init(void) { printk(KERN_INFO "Hello, ARM Kernel!\n"); return 0; } static void __exit hello_exit(void) { printk(KERN_INFO "Goodbye, ARM Kernel!\n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); ``` #### **6.2 编写 Makefile** ```makefile KDIR ?= /path/to/linux-5.9.6 ARCH ?= arm CROSS_COMPILE ?= arm-linux-gnueabihf- obj-m += hello.o all: make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules clean: make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) clean ``` #### **6.3 编译并测试** ```bash make # 将生成的 hello.ko 复制到 QEMU 虚拟机的根文件系统中 # 在 QEMU 中加载驱动: insmod hello.ko dmesg | tail # 查看输出 ``` --- ### **常见问题** 1. **QEMU 启动失败**: - 检查 `zImage` 和 `dtb` 路径是否正确。 - 确认 `vexpress-a9` 机器类型是否支持。 2. **驱动加载失败**: - 确保驱动编译时使用的内核版本与 QEMU 中运行的内核一致。 - 检查 `printk` 输出是否被重定向到控制台(`console=ttyAMA0`)。 3. **网络配置**: - 若需网络支持,在 QEMU 启动命令中添加 `-net user`,并在内核配置中启用网络驱动。 --- 通过以上步骤,你可以在 QEMU 模拟的 ARM 环境中进行完整的内核编译和驱动开发学习。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值