catalog
. 概述
. 使用模块
. 插入和删除模块
. 自动化与热插拔
. 版本控制
1. 概述
模块(module)是一种向Linux内核添加设备驱动程序、文件系统及其他组件的有效方法,而无需连编新内核或重启系统,模块消除了宏内核的许多限制,模块有许多优点
. 通过使用模块,内核发布者能够预先编译大量驱动程序,但并不会造成内核镜像发生膨胀,在自动检测硬件(例如USB)或用户提示之后,安装例程选择适当的模块并将其添加到内核中
. 内核开发者可以将试验性的代码打包到模块中,模块可以卸载、修改代码或重新打包后可以重新加载,这使得可以快速测试新特性,无需每次都重启系统
模块几乎可以无缝地插入到内核,模块代码导出一些函数,可以由其他核心模块(包括持久编译到内核中的代码)使用,同样,在模块代码需要卸载时,模块和内核剩余部分之间的关联,也会相应终止
aaarticlea/png;base64,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*jNObToQC1Wq1YLDLGnp+fjcwnu71Eq4QEBsS+IIoiCCGKzMeDsaJOr7W95HQUEjDwBK0ixliz2aSJBl3knF9dXWnDpVQqmZg/nU6l2T5O4zBtckDYUHUcf6NELwlt5nnecrmkUR0Vyjmv1Wq0rEqOs0Q7iDylnkILbXhZYpErQWkJ5bUDZ6SSxYe6PEWy31L+WulQTOXYC/kJqDWv3nIEY6xSqfQSqXioiWLJudFoSLN9MJ/eJblOBQDDD/23MvqFm5ubWq0mKQIQ89FxIBc2uTEfJx9tzGeCIKEnnD8xn8/BZJYIDGAy7Ps+pEVIipQyIj0YLvKt1WpReoo2xlij0SB/1m7MXywWxWJRPYFLZT4sV18o0D2LExByBG9iaD++yXx6YeGCTIW0OYJpv9ZsFZa4FIMyNctax3xterUoMaOjnS5epJqtvZVaZi6QnDXZ7IjLy0tSIhCZDzE8MTYww1UXyNjmUpT4G50FRlnplsR8LggHDodDGn7W6jd8jLHlcnl6egqldOwlDgYDGqtXq9V4PH56euKch2HYarVmsxlk0geDQafTWa1WQRBIzO92u/P5fDabVSqVyWRCu9x3d3ec89FoVKlUptMp+po4ji8uLpbLpSRovVqtJOZLrVKtVguFAmhfKBQqlYp2wMcHC0EQxHEcxzGleXt7K5fLX19fnuc9PDyA+fV6PY7jcrn88fHh+z5NUqCLOBqNut0uKm06nUIvfbVa9fv9+/v7xWIRx/FwODw+Pg6CYLFYaMNIjDw1+ERP1eyO0awGcWr0Sya5MMdUuOqyxSlTDai5TPZngukpqjHuYIxdX1/ThjyFE+f89vaWRmnsxkN9/Pv7G3nFT4Ak0M4/Tjf4/PwUvwtCRmL++fl5v9+P43gymVSrVcbY6+vrBvNFJ2mVC4tbnue9v7/Twh44jC7q7OxsnuiceokCie/7SE9rWpje93o9mmmwRAIRoOW3+eYpq81mE2/UUoVaxnyebJCA+bTCoQJrlnRgK54CAzzP6/f7GNLhIKmvhGEoKk/hpYtzPplMkLG9KfYUhiHezTDr027sSdDyR/tbvJga1tqU3Mwr00PFvC5wZJeaUmuM9pbJKcuVLRzJina7LYqL0q5eFEVY4ePCdq9WCFAiP9sEhvHZbEbvAtSb9Hq9l5cX1SR8UEQz67XEfPUZkmQVFzoYMTEWJMX0UlFaZTXxuSafpVylUqmnnKglGu/7PrbxvbRDNfnmJIpg+fhRnYZlTZkp2tTYlX7zNPLz3ZjPDb1MVhdMeSVHTHlNxqjlW7ww1Y/20bsAQ4hIAVon9n3/6OiIBqS2TkqQKyzAGj4Jk9F3PhAao600+pLn8fGR614QaF8Mvm+vySP6xt34kKlkLTDmWxJEUQQ1rtQBNl9kpYR7mVpKmFJaYHqE/YqFqy6lucOd+RJptUy2XMlUP1uAKUrH4och9EkPUz6/t5ep0k2ClFJbCH6kMN+SX6J6jpxPBXb1tPMFLnwXkVV1e8eGzzFu1Hh1zyUGsT2yt3iEmjdf/BzzU3luyv4TbhLs01sXWFYETBBrYNcxf884OTmhHXhtAmbQY1ahhtQvgbthJgJoI95UYI7M36VKVQtNDExlvja9JVlqFfH8xPByF9Vzh1QJmcd8bYK99QI4URi/TS3t0pu6NPZvgMRh7V1uGNZcWMFzZf4uJe+T+Wrr26vor8T+TtE23do68kwNtkU3tOdWd+RkanoTAexRrhYuFpJqiaOPWfNaLLRksXhqT2m6+DshvcynQhskEvbEfNqutCNT7WdqLcewc3+uS5a8pnaWgJZMssS3WpSlF8hqiaMX22W0G+NYrJbkP0r7HCf22MbPqzTgP1PQHHDAAX8xDsw/4IB/EQfmH3DAv4g/16jOSXVc0goAAAAASUVORK5CYII=" alt="" />
Relevant Link:
2. 使用模块
添加和移除模块涉及几个系统调用,这些通常由modtils工具包调用
0x1: 添加和移除
从用户的角度来看,模块可通过两个不同的系统程序添加到运行的内核中
. modprobe: 考虑了各个模块之间可能出现的依赖性,即在一个模块依赖于一个或多个合作者模块的功能,modprobe在识别出目标模块所依赖的模块之后,在内核也会使用Insmod
. insmod: 只加载一个单一的模块到内核中,而该模块可能只信赖内核中已存在的代码,并不关注所依赖的代码是通过模块动态加载,还是持久编译到内核中
模块文件是可重定位的,可重定位文件的函数都不会引用绝对地址,而只是指向代码中的相对地址,因此可以在内存的任意偏移地址加载,当然在映像加载到内存中时,映像中的地址要由动态链接器ld.so进行适当的修改,内核模块也是一样的,内核模块中的地址也是相对的,而不是绝对的,但重定位的工作由内核自身执行,而不是动态装载器
在处理init_module系统调用时,模块代码首先复制到内核内存中,接下来是重定位工作和解决模块中未定义的引用,因为模块使用了持久编译到内核中的函数,在模块本身编译时无法确定这些函数的地址,所以需要在这里处理未定义的引用,这些函数定义在内核的基础代码中,因为已经加载到内存,为此,内核提供了一个所有导出函数的列表,该列表给出所有导出函数的内存地址和对应函数名,可以通过proc文件系统访问
cat /proc/kallsyms
这是对于内核中持久编译的代码和动态添加的模块导入的代码的数组,其数组项用于将符号分配到虚拟地址空间中对应的地址
0x2: 依赖关系
一个模块还可以依赖一个或多个其他模块,在向内核添加模块时,还需要考虑下列问题
. 内核提供的函数符号表,可以在模块加载时动态扩展其长度,模块可以指定其代码中哪些函数可以导出,哪些函数仅供内部使用
. 如果模块之间有依赖,那么向内核添加模块的顺序很重要,否则会造成函数引用的地址无法解析,modutils标准工具集中的depmod工具可用于计算系统的各个模块之间的依赖关系,每次系统启动时或新模块安装后,通常会运行该程序,找到的依赖关系保存在一个列表中,默认情况下,写入/lib/modules/2.6.-.el5(对应ersion)/modules.dep中,该信息由modprobe处理,该工具在现存的依赖关系能够自动解决的情况下向内核插入模块
depmod分析所有可用的模块的二进制代码,对每个模块建立一个列表,包含所有已定义符号和未解决的引用,最后将各个模块的列表彼此进行比较,如果模块A包含的一个符号在模块B中是未解决的引用,则意味着模块B依赖模块A,接下来在依赖文件中以B:A的形式增加一项,即确认了上述事实,模块引用的大多数符号都定义在内核中,而不是定义在其他模块中
0x3: 查询模块信息
有一些额外信息,是直接存储在模块二进制文件中,并且指定了模块用途的文本描述,这可以使用modinfo工具查询
. 驱动的开发者
. 驱动程序的简短描述
. 可以传递给模块的配置参数
. 指定支持的设备
. 该模块按何种许可证分发(重要)
0x4: 自动加载
通常,模块的装载发起于用户空间,由用户或者自动化脚本启动,在处理模块时,为达到更大的灵活性并提高透明度,内核自身也能够请求加载模块,由于在用户空间完成这些比内核空间容易得多,内核将工作委托给一个辅助进程kmod,kmod并不是一个永久性的守护进程,内核会按需启动它
内核源代码中,很多不同地方调用了request_module,借助该函数,内核试图通过在没有用户介入的情况下自动加载代码,使得尽可能透明地访问那些委托给模块的功能
3. 插入和删除模块
用户空间和内核的模块实现之间的接口,包括以下几个系统调用
. init_module: 将一个新模块插入到内核中,用户空间工具只需要提供二进制数据,所有其他工作(特别是重定位和解决引用)由内核自身完成
. delete_module: 从内核移除一个模块(前提是该模块的代码不再使用,并且其他模块也不再使用该模块导出的函数,否则强行卸载会造成内核地址引用错误PANIC)
. reque_module(非系统调用): 用于从内核端加载模块,它不仅仅用于加载模块,还用于实现热插拔功能
0x1: 模块的表示
我们接下来讨论在内核中表示模块(及其属性),其中,module是最重要的数据结构,内核中驻留的每个模块,都分配了该结构的一个实例
\linux-2.6.32.63\include\linux\module.h
struct module
{
/*
state表示模块的当前状态
enum module_state
{
MODULE_STATE_LIVE, //正常运行
MODULE_STATE_COMING, //装载期间
MODULE_STATE_GOING, //正在移除
};
*/
enum module_state state; /*
Member of list of modules, 用作模块链表的链表元素
list是一个标准的链表元素,在内核使用,将所有加载模块保存到一个双链表中,链表的表头定义为全局变量modules
*/
struct list_head list; /*
Unique handle for this module 该模块的唯一句柄
name指定了模块的名称,该名称必须是唯一的,内核中会使用该名称来引用模块
*/
char name[MODULE_NAME_LEN]; /* Sysfs stuff. */
struct module_kobject mkobj;
struct module_attribute *modinfo_attrs;
const char *version;
const char *srcversion;
struct kobject *holders_dir; /* Exported symbols 导出的符号 */
const struct kernel_symbol *syms;
//crcs也是num_syms个数组项的数组,存储了导出符号的校验和,用于实现版本控制
const unsigned long *crcs;
unsigned int num_syms; /* Kernel parameters. */
struct kernel_param *kp;
unsigned int num_kp; /* GPL-only exported symbols. 只适用于GPL的导出符号 */
unsigned int num_gpl_syms;
const struct kernel_symbol *gpl_syms;
const unsigned long *gpl_crcs; #ifdef CONFIG_UNUSED_SYMBOLS
/* unused exported symbols. */
const struct kernel_symbol *unused_syms;
const unsigned long *unused_crcs;
unsigned int num_unused_syms; /* GPL-only, unused exported symbols. */
unsigned int num_unused_gpl_syms;
const struct kernel_symbol *unused_gpl_syms;
const unsigned long *unused_gpl_crcs;
#endif /* symbols that will be GPL-only in the near future. */
const struct kernel_symbol *gpl_future_syms;
const unsigned long *gpl_future_crcs;
unsigned int num_gpl_future_syms; /* Exception table 异常表 */
unsigned int num_exentries;
struct exception_table_entry *extable; /* Startup function. 初始化函数 */
int (*init)(void); /*
模块的二进制数据分为连个部分
1. 初始化部分: 装载结束后都可以丢弃,例如初始化函数
2. 核心部分: 包含了正常运行期间需要的所有数据
*/
/* If this is non-NULL, vfree after init() returns 如果不是NULL,则在init()返回后调vfree释放 */
void *module_init;
/* Here is the actual code + data, vfree'd on unload. 这是实际的代码和数据,在卸载时调用vfree释放*/
void *module_core; /* Here are the sizes of the init and core sections module_init、module_core两个内存区的长度 */
unsigned int init_size, core_size; /* The size of the executable code in each section. 上述两个内存区中可执行代码的长度 */
unsigned int init_text_size, core_text_size; /* Arch-specific module values 特定于体系结构的值 */
struct mod_arch_specific arch; /*
same bits as kernel:tainted
如果模块会污染内核,则设置taints,污染意味着内核怀疑该模块做了一些有害的事情可能妨碍内核的正确运行,模块可能因为两个原因污染内核
1. 如果模块的许可证是专有的,或不兼容GPL(即没有声明GPL),那么在模块载入内核时,会使用TAINT_PROPRIETARY_MODULE
2. TAINT_FORCED_MODULE表示该模块是强制装载的,如果模块中没有提供版本信息,也称作版本魔数(version magic),或模块和内核某些符号的版本不一致,那么可以请求强制装载
*/
unsigned int taints; #ifdef CONFIG_GENERIC_BUG
/* Support for BUG */
unsigned num_bugs;
struct list_head bug_list;
struct bug_entry *bug_table;
#endif #ifdef CONFIG_KALLSYMS
/*
* We keep the symbol and string tables for kallsyms.
* The core_* fields below are temporary, loader-only (they
* could really be discarded after module init).
kallsyms的符号表和字符串表
KALLSYMS是一个配置选项(但只用于嵌入式系统,在普通计算机上总是启用的),启用该选项后,将在内存中建立一个列表,保存内核自身和加载模块中定义的所有符号(否则只存储导出的函数)
如果oops消息(内核检测到背离常规的行为,例如反引用NULL指针),不仅输出16进制数字(地址),还要输出涉及函数的名称,那么该选项就很有用
*/
Elf_Sym *symtab, *core_symtab;
unsigned int num_symtab, core_num_syms;
char *strtab, *core_strtab; /* Section attributes 模块中各段的属性 */
struct module_sect_attrs *sect_attrs; /* Notes attributes note属性 */
struct module_notes_attrs *notes_attrs;
#endif /* Per-cpu data. per-cpu数据,它在模块装载时初始化 */
void *percpu; /* The command line arguments (may be mangled). People like keeping pointers to this stuff */
char *args;
#ifdef CONFIG_TRACEPOINTS
struct tracepoint *tracepoints;
unsigned int num_tracepoints;
#endif #ifdef CONFIG_TRACING
const char **trace_bprintk_fmt_start;
unsigned int num_trace_bprintk_fmt;
#endif
#ifdef CONFIG_EVENT_TRACING
struct ftrace_event_call *trace_events;
unsigned int num_trace_events;
#endif
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
unsigned long *ftrace_callsites;
unsigned int num_ftrace_callsites;
#endif #ifdef CONFIG_MODULE_UNLOAD
/*
What modules depend on me? 依赖当前模块的模块
modules_which_use_me用作一个链表元素,将模块连接到内核用于描述模块间依赖关系的数据结构中
*/
struct list_head modules_which_use_me; /*
Who is waiting for us to be unloaded 等待当前模块卸载的进程
waiter是一个指针,指向导致模块卸载并且正在等待该操作结束的进程的task_struct实例
*/
struct task_struct *waiter; /* Destruction function. 析构函数 */
void (*exit)(void); /*
引用计数
系统中每个CPU,都对应到该数组中的一个数组项,该项指定了系统中有多少地方使用了该模块
*/
#ifdef CONFIG_SMP
char *refptr;
#else
local_t ref;
#endif
#endif #ifdef CONFIG_CONSTRUCTORS
/* Constructor functions. */
ctor_fn_t *ctors;
unsigned int num_ctors;
#endif
};
0x2: 依赖关系和引用
如果模块B使用了模块A提供的函数,那么模块A和模块B之间就存在依赖关系,可以用两种不同的方式来看这种关系
. 模块B依赖模块A,除非模块A已经驻留在内核内存,否则模块B无法装载
. 模块B引用模块A,除非模块B已经移除,否则模块A无法从内核移除,即所有引用模块A的模块都已经从内核移除。在内核中,这种关系称之为模块B使用模块A
为了正确管理这些依赖关系,内核需要引入另一个数据结构
\linux-2.6.32.63\kernel\module.c
/* modules using other modules */
struct module_use
{
struct list_head list;
struct module *module_which_uses;
};
依赖关系的网络通过module_use、module->modules_which_usr_me成员共同建立起来
. 对每个使用了模块A中的函数的模块B,都会创建一个module_use的新实例
/*
struct module_use
{
struct list_head list;
struct module *module_which_uses;
};
*/
. 将新module_use实例的module_which_uses指针指向模块B的module实例
. 该新module_use实例将添加到模块A的module实例中的modules_which_use_me链表
根据这些信息,内核很容易计算出使用特定模块的其他内核模块
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAkMAAADzCAIAAAAKDoWQAAAgAElEQVR4nOx9UYicyXHwEg7C4gdBHibkQQbDYhxWnJ2M4PKzCD+MIidZiTOejSPIWAKhkZCNJJTYsyx62NsoODur6ExWiAvMiiigPcsmqFlCWGVfzLCHMafVQ/hgL5As9kMCnwzxy7zcU3//Q2XKNVXV9fX3zTerVU71MHzTXV1dXVVd1d1fd39TWZZlWea9zwRAoh8CTWdZE4LIGinO4TA2IWAN8aNKKUREhQmwnMNJiaxcZGaumCjNQLXeEtI4fMuPgVDfDKneyLXBl7LDw4Q0TUvjRCrXFm9Ibj5PdEw7NF1lMlRLLmMhaqbMjhAY0gOYkkgxKrElZeBHcilLvV5yZ1Ca+Szsmo8+HEJvMWyMiS6Gjops2+0htDEXZDcxZDImvMJmhiAlEMIZDAY2QqFmxki1XFtsrmz6mJ6Lf5S1WQhoA6doqzLhN3MhFzNUcUyujW+UrVhgoxWVKzVOQVsaMYqQnKssVSi6w1EHre41JV45hIzEk4ZE9ib1rw3peCCphSjL9FDB1xTULmwownAOMbobDAZ+KMzqGvFrALLj08fiTCy/npMZjY8XR7ygY6AEZf/GqR0WpGmaO9T9bAJzuJHyqUqStHvLLJardjfmCo1aJP/YhPi2gA9lRKh1jR8UjawQS1KJ8S0qzfBgMJB+WGpNBalKVbnPnz93Q+j1em4UegK63S78wgM+I3Q6HfZXTSkEbQLwlybu7Ox4Me+awif/xk1HwBERUWr6i0K9zihO+zClGe8RVBhThq9WBdTtHjJI+UulyFLqIC932BcfydI0TZLEOQe/uSB9pQHd4sB8YsiTSkdJs1qtVnsUmgWhMQpqooSHDx/KIYUcWKhKCUU+lnjhwgWsrl6v57I0Pz9ftO0hQDG2IyAU5JrN5t///d9Lw56KjGHxHbhoV4/HT9MUkAeDwaeffqrifPrpp4PBIETTHtQcgpNSh5n7+/v4kAt7e3v7+/v9fr/f79NEBPr3Zz/72e7u7t7e3m4Ynj17tru765zbGYWtrS38/ad/+qcPh7C1tbW1tfWEwNbW1sOHDx8+fAjP4wRRG+QAE6X64MGDu3fv3r1792/+5m/u3r17h8CtW7cg69YoLI0CJt66devqEG7evLm4uHhTg8XFxStXrsDvlStXvv3tb1+5cuXGjRuXw3B9FLDT0mdMAWi1WlD22rVr169fX1xcXFxcpDRvDKHZbLZaLRRIvPQMUcdgOudmZ2dBXCDA733ve/AMvwgUB+S8ZML3v/99lrIyhLW1tfth2BDwj//4jxsbG48j4OnTp0+fPv3Rj370+PHj9fV1/H369Cn8Pnv27CmBjY2Np6MAKVAvJm4T2NjYwOd+v7+9vb25uQl///Zv/zakDvpgRzI1EdNv3LjhnAMHsrm5iUOQZ8+e0QFHv99nz/1+P0mS/hAwJTSCoRSgICInBD7++GNJBGuhBeF5fX39L/7iL/b29pifmVLbL73twcGBTEzCANWPM0DDyWxoaEbnsKEAniRJTG/EVscjlwPnXF0ADI4Q5ubmaCIdH7EUeIZBEx39yfEge5DjLBw2wohJneYboyd8npmZcc7ZQpjEpKper3c6HactmIwJaMaqPWMi9NvIeYlRF6VDqWE65YdCt9ttNBrqzEwOzP1orArlxmjKOVev16XYDVEY7i8SqHejBJlMnHPgpg4ODqSPkvgsVyLQeikR5rWpVUiabjQGUE7Onj1rey2pKZaFz+wB4fLly7KNIR0ZQstVJU1PhGFTkao8hKTd6/VOnDjRaDTcqJ9R5mRpmoZcp/Sq0ikDzM3NMZzcOSx1piFAj8wmrQitVgsSO50OeLfcrngIgLG/1+tBt0dwo843xhEnws3F4BcCZrghgrQDO+egdS4vklUIaLfoTFUHwXwNbWNuBFI9kQQZaTBd9l7VQaj15tLHxE6nMzMzExrAGbHKiHPjRDIDZCtUrdlFXMAyK4QYggaOE5GMFpEzAZCk9NFem5PZcy8jkt24cUMyw4RJEWQwlulUHYwsgoxkmE7/2qp0zvV6vZmZmUaj0ev1aLumWDsHg0GSJPV6nU6JIsE2XwmSeybWhDgg1lqYF8uy1GFBPMvtiocJzjmwVEd8nCoNmSWNxo3q2wkzMmbGqjVLtxsqqz6AkbXb7e3t7TEFBYE/cr0Xxl7dblcVjtqEXLBH3yzdiaAuZUVT1N6u9n8neoQ0A/jtdrszMzPgClkn99GRTOLnCt+RSCatSJUD00tIRyHfZxRErWGcsJeOioIbVb0KWKONzBgD/ufm5prNpouIZFIRajCTmFeuXGGVJkLCEkEKIWTwIY2HhozqEFP+xUQ1kmW448OTtbUkSWCNKBHGR5unphs4yLcqL1VYSSCSSXEweQHAHA6i7CGsHOZCmqaORDKpqmToCNTWybCUaO5AVYEqq5Cx2gVdWP5gZDMzMzdv3qxWbrb6IJLB6qJslBMRiElVFYsEJmRbFJirajMRERFJsSFqqF+wB+dct9ut1WqhSCYhdzYWGclwmSEkUlVQquk60hconRhpM+kVBTXgSfnH0Kd8sqGhqlOahZEsHd1rHqOIkIpZooxk8HbGUJYUdRIRyZxz8N4BRUETm80mm/zYlSIUmJOlaQprRLS1TlOAC7tdAxLNLpnVqvZEKdj1goyazSa0udlsHv1I5oiJhFodKVXakewiTMJF52RydREi2dLS0mEKnEYyVRSqwaiuRyaqaCFRUKHlSk9NV1lyoxMU1joAiGRqJ6dgzMkYWtE5GTqm9fV1OkWLabIhUgB7yYfmSjeVaK/tJY7MgudutwtuN2QqFOBtJawGhVrttPdk0AR1IJKrBRuB5bJIliQJxBX2qi/EOWatr68zuUnodrt0lJMMh1yQThdRWMdBrTmtG87MzIBGaLt4JPOBOZmkSCsz0JzoclIoiZh7MguTnBhZ+NxsNnGUehQimR9dXVQhCbw9ZsqmENK3MyMZkzCrTgpTClk6F4hktVrt6tWrFQo8Zk6GOz7AR/R6PTbMVJtP5cay1FVE1eSMKnKzpAzlRIQBOFbZutKRLIRWenXx6tWrENhodzbkUNSH2rlonN1uF/VljGOkipPRIZ1zjo2TQgCYVKdra2vABmMvtBNk/EhmD1C891euXHGjPR1lRTmREyaGAFpmCFgQ+iDO17vd7vr6OiWIIgXV9MiRNcRZX1/vdDrUloAsNXJsYDCSQWGmYEP9rD22FCQmUzY+y0UYTKdVM3yAdrtdq9VgiJQU2cQ4CQBf7EYHsExzzpxuhsS1vb2NC2sUrdfrLS8v48BHpaZKFYCOpNS3kpIZMFyIZIcsW4hk2Ch4aUR5C63Nhqah/X6fbSFhomDTDgZUre12m7p1N9QymgFTgRSsIx3eOQe7nFiRyEgGoM7A5EO5SLaxsQGsMuFEv*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" alt="" />
如果试图装载一个模块,却因为依赖的模块不存在,而导致一部分未定义的符号无法解决,内核将返回错误码并放弃装载,需要明白的是,依赖关系的处理,需要由用户空间的modprobe来处理
内核提供了already_uses函数,来判断模块A是否需要另一个模块B
\linux-2.6.32.63\kernel\module.c
/* Does a already use b? */
static int already_uses(struct module *a, struct module *b)
{
struct module_use *use; /*
如果模块A依赖模块B,则模块B的modules_which_use_me链表中必定至少有一个链表元素的module_which_uses成员指向了模块A的module实例的指针
*/
list_for_each_entry(use, &b->modules_which_use_me, list)
{
if (use->module_which_uses == a)
{
DEBUGP("%s uses %s!\n", a->name, b->name);
//如果找到一个匹配项,则依赖关系确实存在
return ;
}
}
DEBUGP("%s does not use %s!\n", a->name, b->name);
return ;
}
use_module用于建立模块A和模块B之间的关系,即模块A需要模块B才能正确运行
int use_module(struct module *a, struct module *b)
{
struct module_use *use;
int no_warn, err; //already_uses首先检查该关系是否已经建立
if (b == NULL || already_uses(a, b)) return ; /*
If we're interrupted or time out, we fail.
将模块B的引用计数器加1,使之不能从内核移除,因为模块A坚决要求模块B驻留在内存中
static inline int strong_try_module_get(struct module *mod)
{
if (mod && mod->state == MODULE_STATE_COMING)
return -EBUSY;
if (try_module_get(mod))
return 0;
else
return -ENOENT;
}
*/
if (wait_event_interruptible_timeout( module_wq, (err = strong_try_module_get(b)) != -EBUSY, * HZ) <= )
{
printk("%s: gave up waiting for init of module %s.\n",
a->name, b->name);
return ;
} /* If strong_try_module_get() returned a different error, we fail. */
if (err)
return ; DEBUGP("Allocating new usage for %s.\n", a->name);
use = kmalloc(sizeof(*use), GFP_ATOMIC);
if (!use)
{
printk("%s: out of memory loading\n", a->name);
module_put(b);
return ;
} use->module_which_uses = a;
list_add(&use->list, &b->modules_which_use_me);
no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);
return ;
}
EXPORT_SYMBOL_GPL(use_module);
对于内核模块的依赖的概念,我们需要明白本质包含的两种概念层次
. 模块安装/卸载的依赖关系
模块A、模块B依次安装,模块B使用了模块A中的某个函数,则模块B依赖于模块A,模块A如果要卸载则必须等待模块B卸载完成之后才可以继续进行 . 模块运行期间函数调用的引用依赖关系
模块A装载进内核内存,并导出了一些函数,用户态或内核态发起了对这个函数的调用,每次调用对增加了一次对这个模块A的引用计数,模块A如果想卸载必须等待这个引用计数降为0时才可以继续进行
0x3: 模块的二进制结构
模块使用ELF二进制结构,模块中包含了几个额外的段,普通的程序或库中不会出现,我们着重讨论这些额外的段
. __ksymtab、__ksymtab_gpl、__ksymtab_gpl_future: 包含一个符号表,包括了模块导出的所有符号
. __param: 存储了模块可接受的参数有关信息
. .modinfo: 存储哎加载当前模块之间,内核中必须先行加载的所有其他模块的名称,即该特定模块所依赖的其他模块
. .exit.text: 包含了在该模块从内核移除时,所需使用的代码(和可能的数据),该信息并未保存在普通代码段中,这样如果内核配置中未启用移除模块的选项,就不必将该段载入内存
. .init_text: 初始化函数(和数据)使用一个独立的段,因为初始化完成后,相关的代码和数据就不再需要,因而可以从内存移除
. .gnu_linkonce_this_module: 提供了struct module的一个实例,其中存储了模块的名称(name)、和指向二进制文件中的初始化函数和清理函数(init、cleanup)的指针,根据本段,内核即可判断特定的二进制文件是否为模块,如果没有该段,则拒绝装载文件
在模块自身和所依赖的所有其他内核模块都已经编译完成之前,上述的一些段是无法生成的,例如列出模块所有依赖关系的段,因为源代码中没有明确给出依赖关系信息,内核必须通过分析目标模块的未解决引用和所有其他模块导出的符号,来获取该信息
生成模块需要执行下述的几个步骤
. 模块源代码中的所有C文件都编译为普通的.o目标文件
. 在为所有模块产生目标文件后,内核可以分析它们,找到附加信息(例如模块依赖关系),保存在一个独立文件中,也编译为一个二进制文件
. 将前述两个步骤产生的二进制文件链接起来,生成最终的模块
1. 初始化和清理函数
模块的初始化函数和清理函数,保存在.gnu.linkonce.module段中的module实例中
<init.h>中的module_init宏、module_exit宏用于定义init函数、exit函数,每个模块都包含上述两个宏定义的代码,用于定义init、exit函数
__init、__exit前缀有助于将这两个函数放置到二进制代码的正确的段中
\linux-2.6.32.63\include\linux\init.h
#define __init __section(.init.text) __cold notrace
#define __initdata __section(.init.data)
#define __initconst __section(.init.rodata)
#define __exitdata __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)
2. 导出符号
内核为导出符号提供了两个宏
. EXPORT_SYMBOL: 用于一般的导出符号
. EXPORT_SYMBOL_GPL: 只用于GPL兼容代码的导出符号
\linux-2.6.32.63\include\linux\module.h
/* For every exported symbol, place a struct in the __ksymtab section */
#define __EXPORT_SYMBOL(sym, sec) \
extern typeof(sym) sym; \
__CRC_SYMBOL(sym, sec) \
static const char __kstrtab_##sym[] \
__attribute__((section("__ksymtab_strings"), aligned())) \
= MODULE_SYMBOL_PREFIX #sym; \
static const struct kernel_symbol __ksymtab_##sym \
__used \
__attribute__((section("__ksymtab" sec), unused)) \
= { (unsigned long)&sym, __kstrtab_##sym } #define EXPORT_SYMBOL(sym) \
__EXPORT_SYMBOL(sym, "") #define EXPORT_SYMBOL_GPL(sym) \
__EXPORT_SYMBOL(sym, "_gpl") #define EXPORT_SYMBOL_GPL_FUTURE(sym) \
__EXPORT_SYMBOL(sym, "_gpl_future")
3. 一般模块信息
模块的.modinfo段包含了一般信息,使用MODULE_INFO设置
/* Generic info of form tag = "info" */
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
这个段中并没有什么特别重要的元素,我们来重点关注"基本的版本控制"这个元素信息,".modinfo"段中总是会存储某些必不可少的版本控制信息,无论内核的版本控制特性是否启用,这使得可以从各种内核配置中区分出特别影响整个内核源代码的那些配置,这些可能需要一个单独的模块集合,在模块编译的第二阶段期间,下列代码会链接到每个模块中
module.mod.c
MODULE_INFO(vermagic, VERMAGIC_STRING);
//VERMAGIC_STRING是一个字符串,表示内核配置的关键特性 \linux-2.6.32.63\include\linux\vermagic.h
#define VERMAGIC_STRING \
UTS_RELEASE " " \
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \
MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \
MODULE_ARCH_VERMAGIC
内核自身和每个模块中都会存储VERMAGIC_STRING的一份副本,因为不同处理器可用的特性可能相差很多,例如,如果模块编译时特意对Pentium4处理器进行优化,那么可能无法插入为Athlon处理器编译的内核中
0x4: 插入模块
init_module系统调用是用户空间和内核之间用于装载新模块的接口,关于init_module的相关知识,请参阅另一篇文章
http://www.cnblogs.com/LittleHann/p/3920387.html
//搜索:3. LKM模块加载原理
0x5: 移除模块
从内核移除模块比插入模块简单得多,关于delete_module的相关知识,请参阅另一篇文章
http://www.cnblogs.com/LittleHann/p/3920387.html
//搜索:4. LKM模块卸载原理
4. 自动化与热插拔
模块不仅可以根据用户指令或自动化脚本装载,还可以由内核自身请求装载,这种装载机制,在下面两种情况很有用处
. 内核确认一个需要的功能当前不可用,例如,需要装载一个文件系统,但内核不支持,内核可以尝试加载所需的模块,然后重试装载文件系统
. 一个新设备连接到可热插拔的总线(USB、FireWire、PCI等),内核检测到新设备并自动装载包含适当驱动程序的模块
//在这两种情况下,内核都依赖用户空间的实用程序,根据内核提供的信息,实用程序找到适当的模块并按惯例将其插入内核
0x1: kmod实现的自动加载
在内核发起的模块自动装载特性中,\linux-2.6.32.63\kernel\kmod.c中的__request_module是主要的函数,模块的名称(或一般占位符)需要传递给该函数。请求模块的操作必须显式建立在内核中,逻辑上一般出现在以下场合
. 内核因为没有可用的驱动程序而导致分配特定的资源失败
. 内核中此类场景有很多,例如IDE驱动程序在探测现存的设备时会尝试加载设备所需的驱动程序,为此必须直接指定所需驱动程序的模块名
0x2: 热插拔
在新设备连接到可热插拔的总线(或移除)时,内核再次借助用户空间应用程序来确保装载正确的驱动程序,与通常插入模块的过程相比,这里有必要执行几个额外的任务,例如
. 根据设备标识字符串,找到正确的驱动程序
. 进行一些配置工作
//这里使用/sbin/udevd完成这些工作
需要明白的是,内核不仅在设备插入与移除时会向用户空间提供消息,实际上内核在很多一般事件发生时,都会发送消息,例如
. 在一个新硬盘连接到系统时,内核不仅提供有关该事件的信息,还发送通知,提供该设备上已经找到的分区信息
. 设备模型的每部分都可以向用户层发送注册和撤销注册事件
//实际上内核可能发送的消息,组成饿了一个相当庞大和广泛的集合
我们通过一个具体的USB的例子来更好地说明这个问题,考虑一个USB存储棒附接到系统,但此时提供USB海量存储(mass storage)支持的模块尚未载入内核,系统想要自动地将设备装载到文件系统,以便用户可以立即访问它,为此,需要执行以下步骤
. USB宿主机控制器在总线上检测到一个新设备并报告给其设备驱动程序,宿主机控制器分配一个新的device实例并调用usb_new_device注册它
. usb_new_device触发对kobject_uevent的调用,该函数对所述对象kobject实例,调用其中注册的特定于子系统的事件通知程序
. 对USB设备对象,usb_uevent用作通知函数,该函数准备一个消息,其中包含了所有必要的信息,使得udevd能够对新的USB海量存储设备的插入、作出适当反应
//udevd守护进程可以检查来源于内核的所有消息
5. 版本控制
不断改变的内核源代码对驱动程序的程序设计有一定影响,特别是只提供二进制代码的专有驱动程序,在实现新特性或修订总体设计时,通常必须修改内核各个部分之间的接口,以处理新的情况或支持性能和设计方面的改进。当然,开发者会尽可能将改动限制到驱动程序不直接使用的那些内部函数,但这并不能排除内核偶尔修改"公开的"接口,很显然,模块接口也会受到此类修改的影响。但是对于厂商发布、只提供二进制代码的驱动程序来说,情况会有所不同,用户不得不等待新驱动的开发和发布,这种情况会引起一整套问题,包括
. 如果模块使用一个废弃的接口,不仅会损害模块的正常功能,而且系统很可能PANIC
. SMP和单处理器系统的接口不同,需要两个二进制版本,如果装载了错误的版本同样可能导致系统崩溃
因此,引入了一个细粒度的方法,从而考虑到内核中各个例程的改变,我们无需考虑实际的模块和内核实现,需要考虑的问题是,如果模块要再不同的内核版本下运作,那么其调用的接口不能改变,所用的方法很简单,但却能很好地解决版本控制问题
0x1: 校验和方法
基本思想是使用函数或过程的参数,生成一个CRC校验和,该校验和是一个4字节数字,如果函数接口修改了,校验和也会发生变化,这使得内核能够推断出新版本已经不再兼容旧版本
1. 生成校验和
内核源代码附带的genksym工具在编译时自动创建,用于生成函数的校验和
2. 将校验和编译到模块和内核中
内核必须将genksym提供的信息合并到模块的二进制代码中,供后续使用,CRC版本控制检测本质上是比较两个东西
. 扫描当前模块中所使用的内核导出函数,这是从装载目标机器的内核中动态获取并计算的,当然这里面还要处理模块间依赖关系
. 模块自身保存的一份CRC Magic数值,这是模块在编译的时候计算并保存的
0x2: 版本控制函数
我们知道,内核使用辅助函数check_version确定模块所需版本的符号是否与内核中可用符号的版本匹配
\linux-2.6.32.63\kernel\module.c
/*
1. sechdrs: 模块段头的一个指针
2. versindex: __version段的索引
3. symname: 将要处理符号的名称
4. mod: 指向模块数据结构的一个指针
5. crc: 指向内核提供的对应符号校验和的一个指针,该校验和在解析该符号时由__find_symbol动态提供
*/
static int check_version(Elf_Shdr *sechdrs,
unsigned int versindex,
const char *symname,
struct module *mod,
const unsigned long *crc,
const struct module *crc_owner)
{
unsigned int i, num_versions;
struct modversion_info *versions; /*
Exporting module didn't supply crcs? OK, we're already tainted.
导出模块没有提供校验和,那么内核已经被污染了,函数直接返回1,这意味着版本检查已经成功,因为如果没有信息可用,那么检查也不会失败
*/
if (!crc)
return ; /* No versions at all? modprobe --force does this. */
if (versindex == )
return try_to_force_load(mod, symname) == ; versions = (void *) sechdrs[versindex].sh_addr;
num_versions = sechdrs[versindex].sh_size
/ sizeof(struct modversion_info); /*
内核遍历该模块所引用的所有符号,从中搜索对应项,并比较模块中存储的校验和与内核返回的校验和
1. 如果两者匹配,则内核返回1
2. 否则发出一条警告信息,并且函数返回0
*/
for (i = ; i < num_versions; i++)
{
if (strcmp(versions[i].name, symname) != )
continue; if (versions[i].crc == maybe_relocated(*crc, crc_owner))
return ;
DEBUGP("Found checksum %lX vs module %lX\n", maybe_relocated(*crc, crc_owner), versions[i].crc);
goto bad_version;
} printk(KERN_WARNING "%s: no symbol version for %s\n", mod->name, symname);
return ; bad_version:
printk("%s: disagrees about version of symbol %s\n", mod->name, symname);
return ;
}
Copyright (c) 2015 LittleHann All rights reserved