主要涉及到module_symbol,module_ref,module这三个数据结构,都在include/linux/module.h中定义。
struct module_symbol
{
unsigned long value;
const char *name;
};
这个结构用来描述符号的名字和值
struct module_ref
{
struct module *dep;
struct module *ref;
struct module_ref *next;
};
这个结构用来描述模块之间的依赖关系,dep表示本模块所依赖的模块,可能是其他模块也可能是内核,内核也是个模块,将内核也定义一个module,
static struct module kernel_module = {
size_of_struct: sizeof(struct module),
name: "",
uc: {ATOMIC_INIT(1)},
flags:MOD_RUNNING,
syms: __start__ksymtab,
ex_table_start: __start__ex_table,
ex_table_end: __end__ex_table,
kallsyms_start: __start_kallsyms,
kallsyms_end: __stop__kallsyms,
};
ref表示其他模块对本模块的引用,然后通过next来构成一个链表。
struct module_persisit;//empty
struct module
{
unsigned long size_of_struct; /* sizeof(module) */
struct module *next;//用来构成链
const char *name;//模块名称
unsigned long size;//模块大小
union {
atomic_t usecount;
long pad;
} uc;//使用次数
unsigned long flags; /* AUTOCLEAN et al */
unsigned nsyms;//符号个数
unsigned ndeps;//依赖模块树木
struct module_symbol *syms;//符号表链
struct module_ref *deps;//依赖模块链
struct module_ref *refs;//被引用模块链
int (*init)(void);//初始化
void (*cleanup)(void);//清除
const struct exception_table_entry *ex_table_start;//异常处理
const struct exception_table_entry *ex_table_end;
/* Members past this point are extensions to the basic
module support and are optional. Use mod_opt_member()
to examine them. */
const struct module_persisit *persist_start;//扩展
const struct module_persisit *persist_end;
int (*can_unload)(void);
};
每个已安装模块在内核中都有一个module数据结构(通过create_module()创建)
创建module的流程为调用sys_create_module()来创建一个struct module,然后就是用sys_init_module()来对module结构进行初始化,从用户空间复制相关成分来填充module结构。
module这个结构大小是一定的,但是其映象空间大小就因模块的不同而不同了。persist_start,persist_end是为了处理用户空间模块大小和内核模块大小不符造成的麻烦,所以在检查时第一要不小于persist_start前面的部分
mod_usr_size>(unsigned long)&((struct module *)0L)->persist_start
第二要小于persist_end+64bytes,mod_usr_size
对于扩展部分的检验用mod_member_present宏来处理,原型为
#define mod_member_present(mod,member) \
((unsigned long)&((struct module *)0L)->member+1) <= (mod)->size_of_struct,
进行完权限以及以上的校验后就可以从用户空间将module结构的相关成分复制过来了,然后就是将module_ref链到相应的模块,最后还要启动执行模块的init_module()函数。
而对模块的卸载则是通过sys_delete_module()来实现的,在该函数中只要将module_ref从相应的链中删除,并且将module结构所占用的空间释放即可。
阅读(953) | 评论(0) | 转发(0) |