结构体struct module在内核中代表一个内核模块,通过insmod(实际执行init_module系统调用)把自己编写的内核模块插入内核时,模块便与一个 struct module结构体相关联,并成为内核的一部分。下面是结构体struct module的完整定义,接下来会逐个解释:
struct module
{
enum module_state state;
struct list_head list;
char name[MODULE_NAME_LEN];
struct module_kobject mkobj;
struct module_param_attrs *param_attrs;
const char *version;
const char *srcversion;
const struct kernel_symbol *syms;
unsigned int num_syms;
const unsigned long *crcs;
const struct kernel_symbol *gpl_syms;
unsigned int num_gpl_syms;
const unsigned long *gpl_crcs;
unsigned int num_exentries;
const struct exception_table_entry *extable;
int (*init)(void);
void *module_init;
void *module_core;
unsigned long init_size,core_size;
unsigned long init_text_size,core_text_size;
struct mod_arch_specific arch;
int unsafe;
int license_gplok;
#ifdef CONfig_MODULE_UNLOAD
struct module_ref ref[NR_cpuS];
struct list_head modules_which_use_me;
struct task_struct *waiter;
void (*exit)(void);
#endif
#ifdef CONfig_KALLSYMS
Elf_Sym *symtab;
unsigned long num_symtab;
char *strtab;
struct module_sect_attrs *sect_attrs;
#endif
void *percpu;
char *args;
};
我们插入一个内核模块,一般会使用工具insmod,该工具实际上调用了系统调用init_module,在该系统调用函数中,首先调用 load_module,把用户空间传入的整个内核模块文件创建成一个内核模块,返回一个struct module结构体。内核中便以这个结构体代表这个内核模块。
state是模块当前的状态。它是一个枚举型变量,可取的值为:MODULE_STATE_LIVE,MODULE_STATE_COMING,MODULE_STATE_GOING。分别表示模块当前正常使用中(存活状态),模块当前正在被加载,模块当前正在被卸载。load_module函数中完成模块的部分创建工作后,把状态置为MODULE_STATE_COMING,sys_init_module函数中完成模块的全部初始化工作后(包括把模块加入全局的模块列表,调用模块本身的初始化函数),把模块状态置为MODULE_STATE_LIVE,最后,使用rmmod工具卸载模块时,会调用系统调用delete_module,会把模块的状态置为MODULE_STATE_GOING。这是模块内部维护的一个状态。
list是作为一个列表的成员,所有的内核模块都被维护在一个全局链表中,链表头是一个全局变量struct module *modules。任何一个新创建的模块,都会被加入到这个链表的头部,通过modules->next即可引用到。
name是模块的名字,一般会拿模块文件的文件名作为模块名。它是这个模块的一个标识。
另外,还要介绍一下宏THIS_MODULE,它的定义如下是#define THIS_MODULE (&__this_module),__this_module是一个struct module变量,代表当前模块,跟current有几分相似。可以通过THIS_MODULE宏来引用模块的struct module结构,试试下面的模块:
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
unsigned int cpu = get_cpu();
struct module *mod;
printk(KERN_ALERT "this module: %p==%p/n",&__this_module,THIS_MODULE );
printk(KERN_ALERT "module state: %d/n",THIS_MODULE->state );
printk(KERN_ALERT "module name: %s/n",THIS_MODULE->name );
list_for_each_entry(mod,*(&THIS_MODULE->list.prev),list )
printk(KERN_ALERT "module name: %s/n",mod->name );
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "module state: %d/n",THIS_MODULE->state );
}
module_init(hello_init);
module_exit(hello_exit);
=========================================
以下均针对于内核2.6.18
在module.h 中 THIS_MODULE的定义如下:
extern struct module __this_module;
#define THIS_MODULE (&__this_module)
即是保存了__this_module这个对象的地址,那这个__this_module在哪里定义呢?这就要从module的编译说起啦,如果编译过模块就会发现,会生成*.mod.c这样的一个文件,打开这个文件,就会发现,类似下面的定义:
struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
.name = KBUILD_MODNAME,.init = init_module,#ifdef CONfig_MODULE_UNLOAD
.exit = cleanup_module,#endif
};
这个文件是调用modpost生成的,modpost的main中有这样一段代码:
for (mod = modules; mod; mod = mod->next) {
if (mod->skip)
continue;
buf.pos = 0;
add_header(&buf,mod);
add_versions(&buf,mod);
add_depends(&buf,mod,modules);
add_moddevtable(&buf,mod);
add_srcversion(&buf,mod);
sprintf(fname,"%s.mod.c",mod->name);
write_if_changed(&buf,fname);
}
其中的add_header就偷偷添加了__this_module 的定义
static void add_header(struct buffer *b,struct module *mod)
{
buf_printf(b,"#include <linux/module.h>\n");
buf_printf(b,"#include <linux/vermagic.h>\n");
buf_printf(b,"#include <linux/compiler.h>\n");
buf_printf(b,"\n");
buf_printf(b,"MODULE_INFO(vermagic,VERMAGIC_STRING);\n");
buf_printf(b,"struct module __this_module\n");
buf_printf(b,"__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
buf_printf(b," .name = KBUILD_MODNAME,\n");
if (mod->has_init)
buf_printf(b," .init = init_module,\n");
if (mod->has_cleanup)
buf_printf(b,"#ifdef CONfig_MODULE_UNLOAD\n"
" .exit = cleanup_module,\n"
"#endif\n");
buf_printf(b,"};\n");
}