简介: 为保持 Linux 内核的稳定与可持续发展,内核在发展过程中引进了可装载模块这一特性。内核可装载模块就是可在内核运行时加载到内核的一组代码。通常 , 我们会在两个版本不同的内核上装载同一模块失败,即使是在两个相邻的补丁级(Patch Level)版本上。这是因为内核在引入可装载模块的同时,对模块采取了版本信息校验。这是一个与模块代码无关,却与内核相连的机制。该校验机制保证了内核装载的模块是用户认可的,且安全的。本文将从内核模块发布者的角度思考模块版本检查机制,并从开发者与授权 root 用户的角度去使用及理解该机制。
内核可装载模块概述
Linux 在发展过程中(即自 Linux 1.2 之后)引进了模块这一重要特性,该特性提供内核可在运行时进行扩展。可装载模块(Loadable Kernel Module,即 LKM)也被称为模块,就是可在内核运行时加载到内核的一组目标代码(并非一个完整的可执行程序)。这就意味着在重构和使用可装载模块时并不需要重新编译内核。模块依据代码编写与编译时的位置可分:内部模块和外部模块,即 in-tree module 和 out-of-tree module,在内核树外部编写并构建的模块就是外部模块。如果只是认为可装载模块就是外部模块或者认为在模块与内核通讯时模块是位于内核的外部的,那么这在 Linux 下均是错误的。当模块被装载到内核后,可装载模块已是内核的一部分。另外,我们使用的 Linux 发行版在系统启动过程 initrd 中已使用了必要的模块,除非我们只讨论基础内核(base kernel)。本文主要是对 Linux 2.6 的外部模块进行讨论的。
可装载模块在 Linux 2.6 与 2.4 之间存在巨大差异,其最大区别就是模块装载过程变化(如 图 1所示,在 Linux 2.6 中可装载模块在内核中完成连接)。其他一些变化大致如下:
模块的后缀及装载工具;
对于使用模块的授权用户而言,模块最直观的改变应是模块后缀由原先的 .o 文件(即 object)变成了 .ko 文件(即 kernel object)。同时,在 Linux 2.6 中,模块使用了新的装卸载工具集 module-init-tools(工具 insmod 和 rmmod 被重新设计)。模块的构建过程改变巨大,在 Linux 2.6 中代码先被编译成 .o 文件,再从 .o 文件生成 .ko 文件,构建过程会生成如 .mod.c、.mod.o 等文件。
模块信息的附加过程;
在 Linux 2.6 中,模块的信息在构建时完成了附加;这与 Linux 2.4 不同