内核树内模块与树外模块,傻傻分不清楚?

内核树内模块与树外模块,傻傻分不清楚?

1. 引言:模块开发的双面抉择

在 Linux 内核开发中,开发者通常需要决定:模块应该放入内核源码树(In-Tree),还是作为独立模块(Out-of-Tree)?

这个问题就像城市规划

  • 树内模块(In-Tree Module) 是核心城区的一部分,享受官方维护、严格审核和稳定性支持。
  • 树外模块(Out-of-Tree Module,OOT Module) 更像是独立产业园区,拥有高度自由,但需要额外维护。

本文将从架构、编译方式、适用场景、调试方法、未来趋势等多角度深入解析,让你彻底弄清这两者的区别与开发实践。


在这里插入图片描述

2. 树内模块(In-Tree Module)解析

2.1 定义

树内模块(In-Tree Module)Linux 内核源码树 的一部分,随内核代码一起发布和维护。例如 drivers/net/ethernet/intel/e1000e

2.2 主要特点

  • 官方维护,长期支持
  • 严格的代码审核流程(LKML 代码审查)
  • 自动兼容新内核版本
  • 无需额外 Makefile,直接集成 Kconfig 系统

2.3 代码示例

1) 目录结构
linux-source/
└── drivers/
    ├── mymodule/
    │   ├── mymodule.c
    │   ├── Makefile
    │   └── Kconfig
2) mymodule.c 示例代码
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
static int __init mymodule_init(void) {
    printk(KERN_INFO "Hello from In-Tree Module!\n");
    return 0;
}
static void __exit mymodule_exit(void) {
    printk(KERN_INFO "Goodbye from In-Tree Module!\n");
}
module_init(mymodule_init);
module_exit(mymodule_exit);
3) Kconfig 配置
config MYMODULE
    tristate "My In-Tree Kernel Module"
    help
      This is a simple in-tree kernel module example.
4) Makefile 配置
obj-$(CONFIG_MYMODULE) += mymodule.o

编译方式:

make menuconfig  # 启用 MYMODULE
make modules

3. 树外模块(Out-of-Tree Module, OOT Module)解析

3.1 定义

树外模块(OOT Module) 是不包含在官方 Linux 内核源码树中的独立模块,通常由第三方维护,如 NVIDIA 驱动。

3.2 主要特点

  • 灵活性高,独立于内核发布周期
  • 需要手动编译和维护,可能出现 ABI 兼容性问题
  • 依赖 DKMS 或手动构建

3.3 代码示例

1) 目录结构
mymodule/
├── mymodule.c
├── Makefile
2) mymodule.c 示例代码
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
static int __init mymodule_init(void) {
    printk(KERN_INFO "Hello from Out-of-Tree Module!\n");
    return 0;
}
static void __exit mymodule_exit(void) {
    printk(KERN_INFO "Goodbye from Out-of-Tree Module!\n");
}
module_init(mymodule_init);
module_exit(mymodule_exit);
3) Makefile 配置
obj-m += mymodule.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
clean:
	rm -f *.o *.ko *.mod.c

编译方式:

make
sudo insmod mymodule.ko
sudo dmesg | tail

4. 对比分析:In-Tree vs Out-of-Tree

维度内核树内模块树外模块
维护者官方内核团队第三方维护者
审核流程严格的 LKML 审查无官方审核
编译方式make menuconfig手动 make
适用场景核心驱动、长期维护第三方驱动、快速开发

5. 高级开发技巧与调试

5.1 动态调试

1) ftrace 调试
echo function > /sys/kernel/debug/tracing/current_tracer
2) Kprobes 调试
#include <linux/kprobes.h>
static struct kprobe kp = { .symbol_name = "do_fork" };
register_kprobe(&kp);

5.2 ABI 兼容性管理

1) 头文件兼容处理
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0)
#include <linux/minmax.h>
#endif
2) ABI 版本检查
modprobe --dump-modversions mymodule.ko

6. 未来趋势:eBPF & Rust for Linux

6.1 eBPF vs 传统模块

特性传统内核模块eBPF
运行环境内核空间用户空间
开发门槛复杂较易

6.2 Rust for Linux

#![no_std]
use kernel::prelude::*;
module! {
    type: HelloModule,
    name: "hello_rust",
    author: "Rustacean",
    license: "GPL",
}

7. 结语

本篇文章不仅解析了 Linux 树内模块树外模块 的概念,还深入剖析了其 开发实践、架构差异、编译方式、调试技巧和未来趋势。无论你是希望将驱动合入主线,还是想独立开发第三方模块,理解这些区别都将帮助你做出最佳技术决策!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值