[TinyLinux-007] 设备驱动裁剪实战:只保留 QEMU 需要的驱动
系列简介:TinyLinux 是由 LabHub 发起的"大道至简"Linux 学习项目。我们通过对内核进行"剔骨"级的物理精简,旨在构建一个 100% 透明、可重现的极简实验室。
公众号:LabHub | 项目仓库:https://gitee.com/lynyujiang/tiny-linux.git
🛠 技术看板
| |
|---|
| 理解设备驱动裁剪策略,仅保留 QEMU 虚拟化环境所需驱动 |
| 驱动子系统架构 / 硬件抽象层 / 虚拟化驱动识别 |
| linux-6.12.51/drivers/ |
| |
| drivers/ 从 500MB+ 精简到 20MB(96% 减少) |
| |
1. 知识点详注 (Technical Glossary)
- **设备驱动 (Device Driver)**:操作系统与硬件设备之间的软件接口。Linux 内核包含数万个驱动,覆盖从 90 年代老硬件到最新 AI 加速卡的所有设备。
- 虚拟化驱动:专为虚拟化环境设计的驱动,如 QEMU 模拟的 virtio 设备、Bochs 显卡等。这些驱动不依赖真实硬件,适合实验环境。
- **块设备 (Block Device)**:支持随机访问的存储设备,如硬盘、光驱、RAM 磁盘。在 Linux 中以
/dev/sd*、/dev/vd* 形式出现。 - **字符设备 (Character Device)**:按字节流方式访问的设备,如串口、键盘、鼠标。在 Linux 中以
/dev/tty*、/dev/input/* 形式出现。 - Kconfig 依赖:驱动配置的依赖关系系统。某些驱动的启用依赖于其他驱动或架构支持。
2. 理论背景 (Deep Theory)
2.1 Linux 驱动子系统为何如此庞大?
完整 Linux 内核的 drivers/ 目录包含:
drivers/ 目录结构(原始大小约 500MB):
├── gpu/ # 显卡驱动(约 100MB)
├── net/ # 网卡驱动(约 80MB)
├── sound/ # 声卡驱动(约 60MB)
├── usb/ # USB 驱动(约 50MB)
├── scsi/ # SCSI 驱动(约 40MB)
├── ata/ # SATA/IDE 驱动(约 20MB)
├── input/ # 输入设备(约 20MB)
├── tty/ # 串口设备(约 15MB)
├── pci/ # PCI 设备(约 15MB)
├── char/ # 字符设备(约 30MB)
├── firmware/ # 固件加载(约 20MB)
└── ... # 其他驱动(约 50MB)
对于 QEMU 虚拟化环境,90% 以上的驱动都是冗余的。
2.2 QEMU 模拟的硬件设备
QEMU 默认模拟以下设备:
2.3 驱动裁剪策略
| | | |
|---|
| 配置禁用 | CONFIG_*=n | | |
| 目录删除 | rm -rf drivers/gpu/ | | |
| 选择性保留 | | | |
TinyLinux 采用选择性保留策略,保留 QEMU 必需的最小驱动集合。
3. 源码与脚本深度走读 (Source Code Dive)
3.1 裁剪后的 drivers/ 目录
# 当前 drivers/ 目录状态
$ du -sh linux-6.12.51/drivers/
20M linux-6.12.51/drivers/
$ ls linux-6.12.51/drivers/
acpi # ACPI 电源管理(保留)
ata # ATA/SATA 驱动(保留,用于 IDE 磁盘)
base # 基础框架
built-in.a
char # 字符设备(保留)
clocksource # 时钟源(保留)
crypto # 加密算法(保留)
firmware # 固件加载(保留)
input # 输入设备(保留,用于键盘)
Kconfig
Makefile
pci # PCI 总线(保留)
rtc # 实时时钟(保留)
tty # 串口终端(保留,核心驱动)
video # 视频输出(保留,基础显示)
3.2 已删除的驱动目录
# 已删除的大型驱动目录
drivers/gpu/ # 100MB - 独立显卡驱动
drivers/net/ # 80MB - 网卡驱动
drivers/sound/ # 60MB - 声卡驱动
drivers/usb/ # 50MB - USB 驱动
drivers/scsi/ # 40MB - SCSI 驱动
drivers/media/ # 30MB - 多媒体设备
drivers/mmc/ # 20MB - SD 卡控制器
drivers/mtd/ # 15MB - Flash 存储
drivers/hid/ # 15MB - 人机接口设备
drivers/leds/ # 10MB - LED 控制
drivers/spi/ # 10MB - SPI 总线
drivers/i2c/ # 10MB - I2C 总线
# ... 以及其他数十个驱动目录
3.3 保留的核心驱动
3.3.1 串口驱动 (tty/)
# 8250/16550 串口驱动 - QEMU 串口通信关键
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=4
3.3.2 块设备驱动 (ata/)
# ATA/IDE 驱动 - QEMU IDE 磁盘支持
CONFIG_ATA=y
CONFIG_ATA_PIIX=y # Intel PIIX/ICH SATA 控制器
3.3.3 输入设备 (input/)
# 键盘支持
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
3.3.4 PCI 总线 (pci/)
# PCI 总线枚举和配置
CONFIG_PCI=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_QUIRKS=y
3.4 内核配置验证
# 检查驱动相关配置
$ grep -E "^CONFIG_(SERIAL|ATA|INPUT|PCI|RTC)=" linux-6.12.51/.config
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_ATA=y
CONFIG_ATA_PIIX=y
CONFIG_INPUT=y
CONFIG_INPUT_KEYBOARD=y
CONFIG_PCI=y
CONFIG_RTC_CLASS=y
4. 配置详解 (Config & Engineering)
4.1 必须保留的驱动配置
| | | |
|---|
| CONFIG_SERIAL_8250 | | |
| CONFIG_SERIAL_8250_CONSOLE | | |
| CONFIG_ATA | | |
| CONFIG_ATA_PIIX | | |
| CONFIG_INPUT | | |
| CONFIG_KEYBOARD_ATKBD | | |
| CONFIG_PCI | | |
| CONFIG_RTC_CLASS | | |
4.2 可以安全删除的驱动
| | |
|---|
drivers/gpu/ | | |
drivers/net/ | | |
drivers/sound/ | | |
drivers/usb/ | | |
drivers/scsi/ | | |
drivers/media/ | | |
drivers/mmc/ | | |
drivers/hid/ | | |
4.3 裁剪脚本示例
#!/bin/bash
# drivers_prune.sh - 驱动目录裁剪脚本
cd linux-6.12.51/drivers/
# 安全删除列表
SAFE_TO_REMOVE="
gpu
net
sound
usb
scsi
media
mmc
hid
leds
spi
i2c
w1
nfc
rapidio
staging
virtio
xen
"
for dir in$SAFE_TO_REMOVE; do
if [ -d "$dir" ]; then
echo"Removing: $dir"
rm -rf "$dir"
# 创建空 Makefile 防止编译报错
mkdir -p "$dir"
echo"obj-y :=" > "$dir/Makefile"
fi
done
echo"Driver pruning complete!"
4.4 裁剪效果对比
5. 工程实验步骤 (Lab Steps)
5.1 验证当前驱动状态
cd /home/devhub/xlabs/tiny-linux
# 1. 检查 drivers/ 目录大小
du -sh linux-6.12.51/drivers/
# 输出:20M linux-6.12.51/drivers/ ✅
# 2. 列出保留的驱动目录
ls linux-6.12.51/drivers/
# 输出:acpi ata base char clocksource crypto firmware input pci rtc tty video
# 3. 检查驱动配置
grep -E "^CONFIG_(SERIAL|ATA|INPUT|PCI)=" linux-6.12.51/.config
5.2 测试串口通信
# 启动 QEMU
./scripts/run_qemu.sh
# 在 TinyLinux 中测试串口
TinyLinux# ls -l /dev/ttyS0
crw-rw---- 1 0 20 4, 64 Mar 8 12:00 /dev/ttyS0
TinyLinux# cat /proc/tty/driver/serial
serinfo:1.0 driver revision:
0:uart:16550A port:000003F8 irq:4 tx:100 rx:0
5.3 测试磁盘访问
# 检查块设备
TinyLinux# ls -l /dev/sd*
brw-rw---- 1 0 6 8, 0 Mar 8 12:00 /dev/sda
# 查看磁盘空间
TinyLinux# df -h
Filesystem Size Used Available Use% Mounted on
none 498.3M 0 498.3M 0% /
5.4 测试键盘输入
# 键盘输入测试
TinyLinux# echo "Keyboard test"
Keyboard test
# 使用方向键和回车键应该正常响应
5.5 如果误删了必要驱动
# 恢复方法:从 git 恢复
cd linux-6.12.51
git checkout drivers/tty/
git checkout drivers/ata/
git checkout drivers/input/
# 重新配置和编译
make tinylinux_defconfig
make -j4 bzImage
5.2 观察点 (Observation Points)
启动日志中的驱动信息:
# 串口驱动加载
[ 0.423463] serial8250: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200)
# ATA 驱动加载
[ 0.360076] pci 0000:00:01.1: BAR 4 [io 0xc040-0xc04f]
[ 0.365000] pci 0000:00:01.1: BAR 0 [io 0x01f0-0x01f7]: legacy IDE quirk
# RTC 驱动加载
[ 0.427754] rtc_cmos rtc_cmos: registered as rtc0
# 无网络驱动加载(预期)
# (无 e1000/virtio_net 相关日志) ✅
# 无声卡驱动加载(预期)
# (无 snd_* 相关日志) ✅
5.3 避坑指南
6. 验证与重现
6.1 驱动目录验证
cd /home/devhub/xlabs/tiny-linux
# 检查 drivers/ 体积
du -sh linux-6.12.51/drivers/
# 预期:20M 左右
# 检查保留的目录
ls -la linux-6.12.51/drivers/ | grep "^d"
# 预期:acpi ata base char clocksource crypto firmware input pci rtc tty video
6.2 启动日志验证
./scripts/run_qemu.sh 2>&1 | grep -E "serial|ata|rtc|input" | head -10
# 预期输出:
# [ 0.423463] serial8250: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200)
# [ 0.427754] rtc_cmos rtc_cmos: registered as rtc0
6.3 功能验证
| | |
|---|
| cat /proc/tty/driver/serial | |
| ls /dev/sd* | |
| echo test | |
| cat /proc/driver/rtc | |
6.4 对应提交
| |
|---|
| 9e35606c4 (refactor: separate configuration from build scripts) |
| git checkout 9e35606c4 |
| source env.sh && ./scripts/make_all.sh |
| drivers/ 约 20MB,bzImage 约 2MB |
⚠️ 注意:Git 提交信息请执行 git log --oneline -5 获取最新提交。
7. 总结与延伸
7.1 本章收获
通过本章,我们掌握了设备驱动裁剪的核心技能:
7.2 思考题
- 如果要添加 USB 存储支持,需要恢复哪些驱动目录?
- 为什么我们保留了
drivers/video/ 而不是完全删除?
7.3 驱动裁剪总结
7.4 下一章预告
在 [TinyLinux-008] 中,我们将探索内核编译优化,进一步减小内核体积并提升启动速度。敬请期待!
🌟 互动与支持
如果你觉得这个项目对理解 Linux 底层有帮助,请不要吝啬你的支持:
- 点赞 & 在看:点击右下角,让更多极客看到这个"活的代码教科书"。
- 关注 LabHub:第一时间获取 TinyLinux 的最新"手术"报告。
- Star 项目:点击 Gitee 仓库地址 给我们一个五星好评!
本文由 LabHub 团队原创,转载请注明出处。
项目地址:https://gitee.com/lynyujiang/tiny-linux.git