kernel-devel
- 定义
全称 Kernel Development Package,是专门为编译 Linux 内核模块(.ko) 提供的完整构建套件,也是你开发驱动 / 内核模块必须安装的包。 - 包含内容(模块编译的核心依赖)
模块编译专用的内核私有头文件(内核内部数据结构、API 定义);
内核编译配置文件 .config(和当前运行内核完全一致);
模块构建 Makefile 脚本、Kbuild 规则;
Module.symvers 符号版本文件(含module_layout等符号的版本哈希,解决模块加载版本冲突);
路径:/usr/src/kernels/(uname−r)/,并软链接到/lib/modules/(uname -r)/,并软链接到 /lib/modules/(uname−r)/,并软链接到/lib/modules/(uname -r)/build(模块 Makefile 的指向目录)。 - 核心用途
唯一用途:编译内核模块(.ko)
模块编译需要依赖内核内部的函数、结构体、符号版本校验;
必须和当前运行的内核版本完全一致,否则就会出现你之前遇到的 module_layout 版本不匹配。 - 版本要求
强制和uname -r输出的内核版本完全相同,一字不差
kernel-headers 里到底有什么头文件?(仅用户态用)
-
kernel-headers 的安装路径是 /usr/include/,核心目录是/usr/include/linux/、/usr/include/asm/,但这里的头文件有严格限制:仅包含内核向「用户态程序」暴露的公共接口定义,完全剔除了内核内部的私有头文件、子系统头文件。
简单说,kernel-headers 的目录里根本没有 sound/ 这个文件夹,也没有drivers/、net/、fs/等内核驱动 / 子系统相关的目录,能找到的只是像linux/types.h、linux/errno.h、sys/socket.h这类用户态程序(比如 gcc、ls、cp 等命令)编译时需要的基础头文件
-
kernel-headers:用户态程序编译用,和内核模块无关;
-
kernel-devel:内核模块编译专属,含模块构建环境 + 符号版本校验信息,是驱动开发必装;
/lib/modules/
/lib/modules/是 Linux 内核模块运行时 + 编译链接的核心根目录 ,所有和内核模块(.ko)相关的运行依赖、编译软链接、系统模块、依赖关系都存放在这里,按内核版本(uname -r)做完全隔离,目录结构和作用和你之前遇到的 模块编译、module_layout校验、insmod/modprobe加载强相关。
一、顶层结构
/lib/modules/
└── [内核版本号]/ # 由 uname -r 得到,每个内核版本独立一套目录,互不干扰
├── build/ # 关键软链接 → 指向 kernel-devel 安装目录
├── source/ # 软链接 → 内核源码目录(一般和 build 同指向)
├── kernel/ # 系统原生内核模块存放目录
├── extra/ # 第三方/自定义编译安装的模块目录
├── modules.dep # 模块依赖关系表
├── Module.symvers # 内核导出符号版本表(含 module_layout)
└── 其他模块元数据文件(alias/symbols/devname等)
所有操作都针对当前运行内核的版本目录 :
/lib/modules/$(uname -r)/
二、核心子项逐一分解(结合你的驱动/模块开发场景)
1. build/(最重要,模块编译的入口)
-
本质 :指向**
kernel-devel安装目录**的软链接(一般到/usr/src/kernels/$(uname -r)/) -
作用 :
编译内核模块时Makefile指向的KERNELDIR就是它,提供完整的模块编译环境 :
内核.config、内部头文件、Kbuild/Makefile 构建脚本、Module.symvers符号版本表。 -
你执行的模块编译命令本质就是跳转到这个目录执行构建:
bashmake -C /lib/modules/$(uname -r)/build M=$PWD modules -
和之前报错的关联:
build/指向的kernel-devel版本不匹配 → 模块编译用的module_layout和运行内核不一致 → 版本冲突。
2. source/
- 软链接,通常和
build/指向同一个内核源码/开发目录,主要用于内核源码级编译,模块开发一般只用build/。
3. kernel/
-
存放内核原生自带的模块 ,按功能子目录分类:
kernel/drivers/ # 各类驱动模块(显卡/网卡/存储/USB) kernel/net/ # 网络协议模块 kernel/fs/ # 文件系统模块 kernel/lib/ # 内核库模块 -
这些是内核发行版预装的标准模块,
modprobe加载系统模块时优先从这里查找。
4. extra/
- 第三方/自定义内核模块 的默认安装目录:
执行make modules_install安装自己编译的驱动、NVIDIA 显卡驱动、虚拟化驱动等,都会被安装到这里。 insmod/modprobe加载第三方模块时,系统也会扫描该目录。
5. modules.dep & modules.dep.bin
- 文本/二进制格式的模块依赖关系表 ,由
depmod命令生成。 modprobe加载模块时,靠这个文件自动加载依赖模块(比如加载tun.ko自动加载依赖的ipv6.ko);insmod不会解析该文件,必须手动加载依赖。
6. Module.symvers(关键符号版本文件)
- 记录内核所有导出符号的版本哈希值 (包括你遇到的
module_layout); - 模块加载时,内核用它和
.ko里的符号版本做校验; - 该文件和
kernel-devel里的Module.symvers完全一致,是模块版本兼容校验的核心依据。
7. 其他元数据文件
modules.alias:硬件ID ↔ 内核模块的别名映射(热插拔/udev 用);modules.symbols:内核导出符号 ↔ 所属模块的映射;modules.devname:设备号/设备名 ↔ 模块的映射。
三、和 kernel-devel/kernel-headers 的关系
/lib/modules/$(uname -r)/build↔kernel-devel
build软链接就是 kernel-devel 的入口 ,没有安装kernel-devel,该软链接指向无效,模块无法编译。- 和
kernel-headers无关
kernel-headers安装在/usr/include,供用户态程序使用,和/lib/modules/目录无任何关联,模块编译也用不到它。
四、常用操作(和该目录相关)
bash
# 1. 重新生成模块依赖与元数据(安装新模块后必执行)
sudo depmod -a
# 2. 查看模块的完整路径
modinfo -n xxx
# 3. 查看当前内核模块目录的软链接指向
ls -ld /lib/modules/$(uname -r)/build
# 4. 清理无效模块/重新生成依赖
sudo rm -f /lib/modules/$(uname -r)/modules.dep
sudo depmod
五、总结(一句话抓核心)
/lib/modules/$(uname -r)/ 是内核模块的「运行仓库 + 编译入口」:
build/软链接对接kernel-devel,提供模块编译环境;kernel/extra/存放所有可加载的.ko模块;- 依赖/符号文件支撑
modprobe加载和符号版本校验 (解决module_layout冲突)。