# arm_qemu_study **Repository Path**: kjfb/arm_qemu_study ## Basic Information - **Project Name**: arm_qemu_study - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-04 - **Last Updated**: 2026-10-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # QEMU 嵌入式 Linux 学习环境 基于 **QEMU ARM (virt) + Buildroot** 的完整学习流程: 从零搭建系统到编写、调试内核驱动模块。 ## 环境说明 | 组件 | 说明 | |------|------| | QEMU 机型 | `virt` (AArch64 Cortex-A53, 64位) | | 内核 | Buildroot 编译的 Linux 内核 (Image) | | 根文件系统 | busybox + ext4 (`rootfs.ext4`) | | 交叉工具链 | Buildroot 自动构建 (output/host/bin) | | 主机↔目标机 | 9p virtfs 共享目录 `share/` (目标机挂载在 /mnt) | ## 快速开始 (按顺序执行) ```bash ./01_install_qemu.sh # 1. 安装 QEMU 及编译依赖 (sudo apt) ./02_download_buildroot.sh # 2. 下载并解压 buildroot ./03_configure_build.sh # 3. 配置 + 编译内核/busybox/rootfs (首次 20~60 分钟) ./04_run_qemu.sh # 4. 启动系统 (退出: Ctrl+A 然后按 X) ``` 登录: 用户 `root`, 无密码。 ## 各脚本详细用法 ### 01_install_qemu.sh 安装 `qemu-system-arm`、`qemu-system-aarch64` 及内核编译依赖 (`bison flex libncurses-dev libssl-dev cpio dwarves` 等)。 ### 02_download_buildroot.sh 从 buildroot.org 下载指定版本(在 `00_env.sh` 中改 `BUILDROOT_VERSION`)并解压。 内含官方 QEMU 参考配置 `qemu_aarch64_virt_defconfig` (注: buildroot 2024.02 起已移除 32 位的 qemu_arm_virt_defconfig)。 ### 06_fast_download.sh / 07_apply_patches.sh `03_configure_build.sh` 编译前会自动调用: - **06_fast_download.sh**: `make show-info` 导出全部组件包清单 → 域名重写为 阿里云镜像(gnu / kernel.org / sourceware) → 并行下载到 `dl/`, 解决官方源在国内极慢的问题(华为云 buildroot 镜像实测不存在, 勿用) - **07_apply_patches.sh**: 外部补丁管理, 见下节 ## 外部补丁管理 补丁统一放在项目目录(与 buildroot 源码树解耦): ``` patches/ └── <包名>/ └── NNNN-描述.patch # 例如 patches/dtc/0001-fix-const-qualifier.patch ``` ```bash ./07_apply_patches.sh # 注入 + dirclean 受影响的包 ./07_apply_patches.sh --no-clean # 只注入, 不清理已构建的包 ./03_configure_build.sh # 重新编译生效 ``` 原理: 通过 `BR2_GLOBAL_PATCH_DIR`(buildroot 官方机制)注册外部补丁目录, 构建对应包时自动应用 `patches/<包名>/` 下的补丁, 无需改动 buildroot 源码树。 添加新补丁只需放入对应包目录后重新运行脚本。 当前补丁: | 补丁 | 作用 | |------|------| | `patches/dtc/0001-fix-const-qualifier.patch` | 修复 dtc 1.7.2 与新版 glibc/gcc 的 const 限定符编译错误 | ### 03_configure_build.sh ```bash ./03_configure_build.sh # 首次编译 (自动并入 9p 配置片段) ./03_configure_build.sh kernel-menuconfig # 打开内核 menuconfig ./03_configure_build.sh busybox-menuconfig # 打开 busybox menuconfig ./03_configure_build.sh buildroot-menuconfig # buildroot 自身配置(包/工具链) ./03_configure_build.sh rebuild # 重新编译 ``` `configs/linux-9p.fragment` 会自动合并进内核 .config, 使能 9p/virtio 共享目录支持和驱动调试选项(`DEBUG_INFO`, `PRINTK_TIME` 等)。 常用内核配置菜单路径: - 驱动调试: `Kernel hacking` → `Kernel debugging` - 9p 文件系统: `Filesystems` → `Network File Systems` → `Plan 9` - KGDB: `Kernel hacking` → `KGDB` ### 04_run_qemu.sh ```bash ./04_run_qemu.sh # 常规启动 ./04_run_qemu.sh snapshot # 快照模式 (rootfs 修改不落盘) ./04_run_qemu.sh gdb # gdbstub 模式, 调试端口 1234 (驱动调试用) ./04_run_qemu.sh kgdb # KGDB 模式 ``` 串口直接输出到当前终端。QEMU 已配置用户态网络并将主机 10022 端口 转发到目标机 22 端口(如目标机装了 dropbear/openssh 可 ssh 登录)。 ## 驱动源码级调试 (QEMU gdbstub + gdb 单步) 前置: `sudo apt install gdb-multiarch`;内核已启用 `DEBUG_INFO`/`GDB_SCRIPTS`。 ```bash # 终端1: gdbstub 模式启动 (系统正常运行, 调试端口 1234) ./04_run_qemu.sh gdb # 终端2: 连接调试 ./08_debug_driver.sh (gdb) c # 让系统继续运行 # ---- 目标机(终端1)里 ---- mkdir -p /mnt mount -t 9p -o trans=virtio,version=9p2000.L host0 /mnt insmod /mnt/hello_cdev.ko # ---- 回到 gdb (终端2) ---- (gdb) lx-symbols /home/jwang/work/qemu/share # 加载/刷新模块符号 (gdb) b hello_write # 驱动函数断点 (gdb) c # ---- 目标机里触发 ---- echo "hi kernel" > /dev/hello_cdev # gdb 在 hello_write 处停下 # ---- 单步调试 ---- (gdb) n # 单步(不进入函数) (gdb) s # 单步进入函数 (gdb) p count # 打印变量 (gdb) p *filp # 打印结构体 (gdb) bt # 查看调用栈 (gdb) finish # 运行到函数返回 (gdb) c # 继续运行 ``` 说明: - `lx-symbols` 是内核自带的 gdb 命令(需 `CONFIG_GDB_SCRIPTS=y`), 能自动解析模块加载地址并加载符号, `insmod` 新模块后重新执行即可 - 驱动 `.ko` 必须带调试信息(未 strip), 由 `CONFIG_DEBUG_INFO=y` 保证 ## 内核跟踪与性能分析 (ftrace / kprobe / perf / proc) 内核配置: `configs/linux-trace.fragment`; perf 工具: `BR2_PACKAGE_LINUX_TOOLS_PERF`; debugfs/tracefs 开机自动挂载: `overlay/etc/init.d/S03debugfs`。 ### ftrace 实验 (目标机里执行) `share/ftrace-demo.sh` 包含 6 个实验, 通过 9p 共享后在目标机运行: ```bash sh /mnt/ftrace-demo.sh # 查看用法 sh /mnt/ftrace-demo.sh 1 # function tracer: 跟踪 hello_* 驱动函数 sh /mnt/ftrace-demo.sh 2 # function_graph: 调用图+耗时 sh /mnt/ftrace-demo.sh 3 # kprobe: 不改代码跟踪 hello_write 及参数 sh /mnt/ftrace-demo.sh 4 # sched 事件: 调度切换跟踪 sh /mnt/ftrace-demo.sh 5 # irqsoff: 最大关中断延迟 sh /mnt/ftrace-demo.sh 6 # /proc 观测: 中断/内存/负载/slab ``` ftrace 接口速查 (`/sys/kernel/debug/tracing/`): ```bash cat available_tracers # 可用 tracer 列表 echo function > current_tracer # 选择 tracer echo 'hello_*' > set_ftrace_filter # 过滤跟踪函数 echo 1 > tracing_on # 开始跟踪 cat trace | head -20 # 查看结果 echo 0 > tracing_on # 停止 ``` ### kprobe 动态探针 (无需修改驱动代码) ```bash T=/sys/kernel/debug/tracing echo 'p:hwrite hello_write buf=$x1 count=$x2' > $T/kprobe_events echo 1 > $T/events/kprobes/hwrite/enable echo "test" > /dev/hello_cdev cat $T/trace | tail -3 # 可看到 buf 地址和 count 值 ``` ### perf 性能分析 ```bash perf stat cat /dev/hello_cdev # 计数器统计(cycles/instructions) perf record -a -g sleep 2 # 全系统采样 2 秒, 含调用栈 perf report # 热点函数排行(方向键浏览, q 退出) perf top # 实时热点 ``` ### /proc 与 /sys 观测 ```bash cat /proc/interrupts # 中断统计 cat /proc/loadavg # 负载 cat /proc/meminfo # 内存 cat /proc/modules # 模块 cat /proc/slabinfo # 内核对象缓存 cat /proc/vmstat # VM 事件 ls /sys/module/hello/ # 模块参数/节 cat /sys/kernel/debug/tracing/available_tracers ``` ### 05_build_driver.sh 用 buildroot 内核树交叉编译 `driver/` 下的所有模块, 拷贝 `.ko` 到 `share/`。 ## 驱动示例 | 文件 | 内容 | |------|------| | `driver/hello.c` | 最简模块: module_init/exit、模块参数、`pr_info` 日志 | | `driver/hello_cdev.c` | misc 字符设备: `file_operations` 的 read/write、`copy_to/from_user` | ### 驱动调试完整流程 ```bash # ---- 主机上 ---- ./05_build_driver.sh # 编译驱动, .ko 自动放入 share/ # ---- 目标机中 (04_run_qemu.sh 启动后) ---- mkdir -p /mnt mount -t 9p -o trans=virtio,version=9p2000.L host0 /mnt # 模块加载/卸载 + 查看日志 insmod /mnt/hello.ko dmesg | tail rmmod hello # 模块参数 (sysfs) cat /sys/module/hello/parameters/cycles echo 3 > /sys/module/hello/parameters/cycles # 字符设备 insmod /mnt/hello_cdev.ko echo "hi kernel" > /dev/hello_cdev cat /dev/hello_cdev dmesg | tail rmmod hello_cdev # 其他常用调试命令 lsmod # 已加载模块列表 cat /proc/devices # 已注册字符/块设备主设备号 cat /proc/interrupts # 中断统计 ls /sys/module/ # sysfs 中的模块信息 ``` ## KGDB 内核调试 (进阶) 1. `./03_configure_build.sh kernel-menuconfig` 打开: `Kernel hacking` → `Compile-time checks` → `Compile the kernel with debug info` `Kernel hacking` → `KGDB: kernel debugger` + `KGDB_KDB` 2. `./03_configure_build.sh rebuild` 3. `./04_run_qemu.sh kgdb` (QEMU 停在入口, 等待 gdb) 4. 主机另开终端: ```bash cd buildroot-*/output/build/linux-*/ ${CROSS_PREFIX}gdb vmlinux (gdb) target remote localhost:1234 (gdb) b hello_init # 给驱动模块入口打断点 (gdb) c ``` ## 常见问题 - **QEMU 退出方法**: 先按 `Ctrl+A`, 松开后再按 `X` - **挂载 9p 报错**: 确认内核配置了 9p (见 `configs/linux-9p.fragment`), 且以 `./04_run_qemu.sh` 启动(带 `-virtfs` 参数) - **改了内核/busybox 配置不生效**: `make linux-rebuild` / `busybox-rebuild` 已由脚本执行; 若仍无效, 到 buildroot 目录 `make linux-dirclean` 后重新编译 - **磁盘空间**: 完整编译约需 10GB+, `output/` 目录可随时删除重编