- 了解THIS_MODULE
1.struct module
结构体struct module在内核中代表一个内核模块,通过insmod(实际执行init_module系统调用)把自己编写的内核模块插入内核时,模块便与一个struct module 结构体相关联,并成为内核的一部分。结构体如下所示:
</include/linux/module.h>
struct module
{
enum module_state state;
/* Member of list of modules */
struct list_head list;
/* Unique handle for this module */
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;
const unsigned long *crcs;
unsigned int num_syms;
/* Kernel parameters. */
struct kernel_param *kp;
unsigned int num_kp;
/* GPL-only exported symbols. */
unsigned int num_gpl_syms;
const struct kernel_symbol *gpl_syms;
const unsigned long *gpl_crcs;
....
}
参数分析:
-
enum module_state state; //state是模块当前的状态。
它是一个枚举型变量,可取的值为:- MODULE_STATE_LIVE,模块当前正常使用中 (存活状态)
- MODULE_STATE_COMING,模块当前正在被加载
- MODULE_STATE_GOING ,模块当前正在被卸载
- MODULE_STATE_UNFORMED, /* Still setting it up. */
-
struct list_head list;
list是作为一个列表的成员,所有的内核模块都被维护在一个全局链表中,链表头是一个全局变量struct module *modules。任何一个新创建的模块,都会被加入到这个链表的头部,通过modules->next即可引用到。 -
char name[MODULE_NAME_LEN];
name是模块的名字,一般会使用模块文件的文件名作为模块名。它是这个模块的一个标识。 -
const struct kernel_symbol *syms;
内核模块导出的符号所在起始地址; -
const unsigned long *crcs;
内核模块导出符号的校验码所在起始地址;
2.THIS_MODULE
THIS_MODULE是一个macro,如下所示:
include/linux/export.h:
14 #ifdef MODULE
15 extern struct module __this_module;
16 #define THIS_MODULE (&__this_module)
17 #else
18 #define THIS_MODULE ((struct module *)0)
19 #endif
THIS_MODULE即是__this_module这个变量的地址,__this_module会指向这个模块起始的地址空间,恰好是struct module变量定义的位置。__this_module 是内核模块的编译工具链为当前内核模块产生的struct module 类型对象,所以THIS_MODULE实际上是当前内核模块对象的指针。
module编译生成的*.mod.c文件包含 __this_module定义:
11 __visible struct module __this_module
12 __attribute__((section(".gnu.linkonce.this_module"))) = {
13 .name = KBUILD_MODNAME,
14 .init = init_module,
15 #ifdef CONFIG_MODULE_UNLOAD
16 .exit = cleanup_module,
17 #endif
18 .arch = MODULE_ARCH_INIT,
19 };
This section contains only one structure–this_module, which is mostly filled with zeroes (as it is used by the LKM loader internally) except three fields:
- Name of the module
- A pointer to the initialization procedure–module_init
- A pointer to the de-initialization procedure–module_cleanup
You may examine content of that section and find module’s name there:
objdump -s -j .gnu.linkonce.this_module foo.ko
Kbuild modpost:
Documentation/kbuild/modules.txt :
When building an external module, the build system needs access to the symbols from the kernel to check if all external symbols
are defined. This is done in the MODPOST step. modpost obtains
the symbols by reading Module.symvers from the kernel source
tree. If a Module.symvers file is present in the directory
where the external module is being built, this file will be
read too. During the MODPOST step, a new Module.symvers file
will be written containing all exported symbols that were not
defined in the kernel.
这个文件是调用scripts/mod/modpost.c(scripts/Makefile.modpost)生成的,代码如下:
2495 for (mod = modules; mod; mod = mod->next) {
2496 char fname[PATH_MAX];
2497
2498 if (mod->skip)
2499 continue;
2500
2501 buf.pos = 0;
2502
2503 err |= check_modname_len(mod);
2504 add_header(&buf, mod);
2505 add_intree_flag(&buf, !external_module);
2506 add_retpoline(&buf);
2507 add_staging_flag(&buf, mod->name);
2508 err |= add_versions(&buf, mod);
2509 add_depends(&buf, mod, modules);
2510 add_moddevtable(&buf, mod);
2511 add_srcversion(&buf, mod);
2512
2513 sprintf(fname, "%s.mod.c", mod->name);
2514 write_if_changed(&buf, fname);
2515 }
其中add_header就添加了__this_module 的定义:
2128 static void add_header(struct buffer *b, struct module *mod)
2129 {
2130 buf_printf(b, "#include <linux/build-salt.h>\n");
2131 buf_printf(b, "#include <linux/module.h>\n");
2132 buf_printf(b, "#include <linux/vermagic.h>\n");
2133 buf_printf(b, "#include <linux/compiler.h>\n");
2134 buf_printf(b, "\n");
2135 buf_printf(b, "BUILD_SALT;\n");
2136 buf_printf(b, "\n");
2137 buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
2138 buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n");
2139 buf_printf(b, "\n");
2140 buf_printf(b, "__visible struct module __this_module\n");
2141 buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
2142 buf_printf(b, "\t.name = KBUILD_MODNAME,\n");
2143 if (mod->has_init)
2144 buf_printf(b, "\t.init = init_module,\n");
2145 if (mod->has_cleanup)
2146 buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
2147 "\t.exit = cleanup_module,\n"
2148 "#endif\n");
2149 buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n");
2150 buf_printf(b, "};\n");
2151 }
其中struct file_operations结构体的第一个成员是struct module类型的指针,定义在<linux/fs.h>中:
struct file_operations {
struct module *owner;
......
}
struct module *owner is commonly used at some structures and is not an operation at all; it is a pointer to the module that "owns"the structure. This field is used to prevent the module from being unloaded while its operations are in use. Almost all the time, it is simply initialized to THIS_MODULE, a macro defined in < linux/module.h> .
struct file_operations中的owner成员可以避免当file_operations中的函数正在调用时,其所属的模块被从系统中卸载掉。如果有一个设备驱动程序不是以模块的形式存在,而是被编译进内核,那么THIS_MODULE将被赋值为NULL,没有任何作用。
参考:
https://www.kancloud.cn/yueqian_scut/emlinux/106822