1. 驱动与 Rootfs 概述
做嵌入式 Linux 开发这么多年,我经常被新人问到一个问题:驱动和文件系统到底是什么关系?为什么非要绑在一起?
说实话,我刚入行时也迷糊过。那时候我总觉得驱动就是 .ko 文件,insmod 一下就能用,跟 Rootfs 有啥关系?直到有一次,我在一个量产项目上栽了跟头——板子启动后驱动死活加载不上,查了两天才发现是 Rootfs 里少了依赖的固件文件。嗯,从那以后,我再也不敢把驱动和 Rootfs 分开看了。
这一章,我们就来把这两个概念彻底捋清楚。
什么是 Rootfs
Rootfs,全称 Root Filesystem,根文件系统。说白了,它就是 Linux 内核启动后挂载的第一个文件系统。
你想想看,内核启动完成后,总得有个地方去读取配置文件、加载应用程序、存放临时数据吧?Rootfs 就是干这个的。它提供了 Linux 系统的目录结构,比如 /bin、/etc、/lib、/usr 这些你熟悉的目录,全都在 Rootfs 里。
我习惯把 Rootfs 比作一个房子的内部装修。内核是房子的骨架和地基,Rootfs 就是里面的水电、家具、装饰。没有装修,房子也能住人吗?能,但你会非常难受。
核心要点:Rootfs 是 Linux 系统启动后赖以生存的根目录环境。没有 Rootfs,内核会 panic,系统直接崩溃。
常见的 Rootfs 类型有几种:
| 类型 | 特点 | 适用场景 |
|---|---|---|
| initramfs | 内存中运行,体积小,启动快 | 早期引导、调试阶段 |
| ext4 镜像 | 传统块设备文件系统,可读写 | 量产产品、需要持久化存储 |
| Squashfs | 只读压缩文件系统,体积小 | 只读场景、固件升级 |
| NFS 挂载 | 通过网络挂载,方便调试 | 开发阶段、快速迭代 |
我个人最常用的是 initramfs 配合 NFS 做开发调试,量产时切到 Squashfs 或 ext4。每种方案都有它的脾气,选对了能省不少事。
驱动在系统中的角色
驱动是什么?我给它一个简单的定义:驱动是内核与硬件之间的翻译官。
硬件听不懂内核的指令,内核也看不懂硬件的寄存器。驱动就是那个两头跑的角色——它知道怎么操作硬件,也知道怎么把硬件的能力暴露给内核和应用程序。
举个例子。你写了一个应用程序要读取温度传感器的数据。应用层只需要调用 open() 和 read(),完全不用管 I2C 总线怎么操作、寄存器地址是多少。这些脏活累活,全是驱动在背后帮你干了。
驱动在系统中的位置大概是这样的:
看到没?驱动在中间层,承上启下。没有驱动,应用层根本碰不到硬件。
为什么需要将驱动集成到 Rootfs
好,现在问题来了:驱动既然是个 .ko 文件,我启动后手动 insmod 不行吗?为什么非要集成到 Rootfs 里?
这个问题,我当年也问过我的导师。他笑了笑,说:你试试量产 10 万台设备,每台都手动 insmod?
我一下就明白了。集成到 Rootfs 不是技术问题,是工程问题。具体来说,有这几个原因:
- 自动化加载——系统启动时自动加载驱动,不需要人工干预。量产产品不可能让人去敲命令。
- 依赖管理——很多驱动有依赖关系。比如你写了一个 I2C 温度传感器驱动,它依赖 I2C 核心模块。如果加载顺序错了,驱动就起不来。集成到 Rootfs 后,可以通过 depmod 和 modprobe 自动处理依赖。
- 固件文件——有些驱动需要额外的固件文件(firmware),比如 WiFi 模组、GPU 驱动。这些文件必须放在
/lib/firmware目录下,而/lib就在 Rootfs 里。 - 设备节点——部分驱动需要静态的设备节点,或者需要 udev/mdev 规则来动态创建。这些规则文件也在 Rootfs 里。
- 模块参数——有些驱动需要传递参数,比如
modprobe driver_name param=value。这些配置可以写在/etc/modprobe.d/里,同样在 Rootfs 中。
我的经验:曾经有一个项目,驱动在开发板上跑得好好的,一上产线就挂。查到最后发现是 Rootfs 里少了 /lib/firmware/ 下的一个固件文件。从那以后,我每次做 Rootfs 都会列一个清单,把驱动依赖的固件、配置、规则文件全部写进去,一个都不能少。
说白了,把驱动集成到 Rootfs,就是把驱动从「手工调试阶段」推进到「自动化量产阶段」的关键一步。
驱动与 Rootfs 的集成关系
驱动和 Rootfs 不是简单的「放进去」关系。我习惯把它们的关系画成一张图:
从这张图能看出来,驱动不是孤零零的一个 .ko 文件。它需要:
- 模块文件放在
/lib/modules/$(uname -r)/ - 依赖信息由 depmod 生成,存在 modules.dep 里
- 固件文件放在
/lib/firmware/ - 加载配置写在
/etc/modprobe.d/ - 设备规则由 udev/mdev 在
/etc/udev/rules.d/管理
这些东西,全都在 Rootfs 里。所以你说,驱动能不集成到 Rootfs 吗?
注意:千万不要把驱动模块直接扔到 Rootfs 里就不管了。我见过有人把 .ko 文件随便丢在 /root/ 目录下,然后写个 rc.local 去 insmod。这种做法在开发阶段勉强能用,但到了量产阶段,依赖管理、版本控制、固件路径全都会出问题。老老实实按标准路径放,用 depmod + modprobe 来管理,才是正道。
小结
这一章我们聊了三个核心问题:
- Rootfs 是 Linux 系统的根文件系统,提供目录结构和运行环境
- 驱动 是内核与硬件之间的桥梁,负责操作硬件并向上提供接口
- 集成到 Rootfs 是为了实现自动化加载、依赖管理、固件配套和量产部署
我个人觉得,理解这三者的关系,是做好嵌入式 Linux 开发的第一步。后面的章节,我们会一步步深入,从编译驱动、制作 Rootfs,到最终把驱动完美集成进去。每一步我都会把踩过的坑、总结的经验分享出来。
嗯,准备好了吗?我们继续往下走。