ESC
输入关键词搜索文章标题和内容

modprobe vs insmod:为什么modprobe比insmod聪明这么多?

本文由 linuxROS 整理发布,首发于 linuxros.cn,转载请注明出处。

modprobe vs insmod:为什么modprobe比insmod聪明这么多?

作者:Linux内核研究员 | 2026-05-06


导读

搞Linux驱动的都懂——insmod动不动就报Unknown symbol,modprobe一上,啥错都没了。很多人懵:不都是加载驱动吗?为啥modprobe就这么聪明?本文从内核源码层面彻底讲清楚它们的核心差异,读完你将彻底掌握模块依赖加载的原理。

适合人群:Linux驱动开发者、嵌入式工程师、内核爱好者


一句话戳穿真相

insmod = 傻憨憨跑腿,只送单个,不问依赖

modprobe = 聪明管家,查家谱、排顺序、把依赖全给你装齐!


1. insmod有多蠢?

你让它装a.ko,它根本不知道a.ko还要靠b.ko和c.ko!它直接硬塞 → 内核找不到符号 → 啪!Unknown symbol报错!

insmod的源码逻辑极其简单(来自kmod项目):

// kmod/libkmod.c - insmod核心逻辑
static int do_load(struct kmod_ctx *ctx, const char *command,
                   const char *args)
{
    // insmod只做一件事:直接加载指定的ko文件
    // 它不会去检查任何依赖关系!
    return kmod_module_probe_insert(ctx, mod, flags, NULL, NULL, NULL);
}

它的脑子只有一句话:

"你让我装我就装,装不上拉倒。"


2. modprobe有多聪明?

它上来先干3件事:

① 翻"家谱"

它去读:/lib/modules/xxx/modules.dep

里面写得清清楚楚:

# modules.dep示例(由depmod工具生成)
a.ko: b.ko c.ko
b.ko: c.ko
c.ko:

② 自动排顺序

它一算:必须先装c → 再装b → 最后装a

③ 自动一个个装

它自己悄悄把依赖全装上,最后再装你要的驱动。你完全不用管!

来自 linuxros.cn · linuxROS

modprobe的源码逻辑(来自kmod项目):

// kmod/libkmod.c - modprobe核心逻辑
static int modprobe_do_format(struct kmod_ctx *ctx, const char *name)
{
    // 1. 先解析modules.dep,获取依赖图
    struct kmod_list *dependencies = NULL;
    kmod_module_get_dependencies(mod, &dependencies);

    // 2. 按依赖顺序排序(拓扑排序)
    // 3. 依次加载每个依赖模块
    // 4. 最后加载目标模块
}

3. 内核层面:模块依赖是怎么工作的?

Linux内核模块加载涉及两个重要数据结构(include/linux/module.h):

// 内核模块结构体(关键字段)
struct module {
    enum module_state state;

    /* 依赖其他模块 */
    struct list_head        source_list;    // 我依赖谁
    struct list_head        target_list;    // 谁依赖我

    /* 模块信息 */
    const char              *name;          // 模块名
    unsigned long           flags;          // 标志位

    // ...
};

内核符号表是解决Unknown symbol的关键:

// kernel/module.c - 内核符号表
static int resolve_symbol(struct module *mod, const struct load_info *info,
                          const char *name, struct module *owner)
{
    // 在内核符号表中查找符号
    // 如果找不到,说明依赖的模块没加载
    // 返回 -ENOSYS 表示符号未定义
}

当你加载a.ko但没加载b.ko时:

insmod a.ko
[    1.234567] a: Unknown symbol b_func (err -2)
[    1.234567] a: Unknown symbol c_data (err -2)

-2就是-ENOENT(没有那个文件或目录),意思是"这个符号在内核符号表里找不到"。


4. modules.dep是怎么生成的?

答案是depmod工具。它扫描所有ko文件,提取MODULE_DEPEND()宏,构建依赖图。

# depmod工作流程
$ depmod -a
# 遍历 /lib/modules/$(uname -r)/
# 解析每个.ko文件的 MODULE_ALIAS() 和 MODULE_DEPEND()
# 生成 modules.dep 和 modules.symbols

实际查看你系统的modules.dep:

$ cat /lib/modules/$(uname -r)/modules.dep | head -20
kernel/drivers/char/tty.ko: kernel/drivers/char/tty_io.ko
kernel/drivers/char/tty_io.ko:
kernel/drivers/char/vt.ko: kernel/drivers/char/tty_io.ko

5. 最形象的段子(秒懂)

insmod:

你让它送个快递,它不管你家有没有人、东西缺不缺零件,扔门口就跑,装不上怪你自己。

modprobe:

像个细心保姆,先查你缺啥,再按顺序给你摆好,最后告诉你:装完啦!


6. 真实工作流程(人话版)

你输入:modprobe a
          │
          ▼
modprobe 查 modules.dep
          │
          ▼
发现 a 靠 b,b 靠 c
          │
          ▼
自动按顺序:c → b → a
          │
          ▼
依次加载,一个不漏
          │
          ▼
完美成功,不报错!

7. 那insmod还有啥用?

场景 用insmod 用modprobe
手动调试单个驱动 ✅ 可以 ❌ 没必要
明确知道没有依赖 ✅ 可以 ❌ 杀鸡用牛刀
加载独立小模块 ✅ 可以 ❌ 杀鸡用牛刀
正经干活、正式环境 ❌ 容易报错 ✅ 永远用它

8. 终极总结(记这4句)

序号 结论
1 insmod只装单个,不管依赖,容易报错
2 modprobe查依赖、排顺序、自动装全套
3 Unknown symbol基本都是由insmod误用导致
4 正式环境,永远优先modprobe

附录:相关命令速查

操作 命令
加载模块 modprobe 模块名 / insmod 路径/模块.ko
卸载模块 modprobe -r 模块名 / rmmod 模块名
查看已加载 lsmod
查看模块信息 modinfo 模块名
查看依赖 modprobe --show-depends 模块名
强制加载(忽略依赖) insmod --force 路径/模块.ko

看完还不懂?记住这个原则:

遇到模块加载问题,第一反应是换成modprobe,而不是--force!


参考资料:Linux内核源码、kmod项目、内核模块文档

版权声明

作者linuxROS
协议本作品采用 CC BY-NC-SA 4.0 许可协议:署名-非商业性使用-相同方式共享
关注欢迎关注微信公众号 linuxROS,获取更多机器人 / 嵌入式 / Linux 干货
返回首页