1、SYSCALL_DEFINE3宏定义
//include/linux/syscalls.h
#define __SYSCALL_DEFINEx(x, name, ...) \
asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))
#define SYSCALL_DEFINEx(x, sname, ...) \
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
2、sys_init_module()函数定义
SYSCALL_DEFINE3(init_module, void __user *, umod,
unsigned long, len, const char __user *, uargs)
//将宏定义展开
asmlinkage long sys_init_module(void __user *umod, unsigned long len,
const char __user *uargs);
sys_init_module()函数不是直接定义的,是利用SYSCALL_DEFINE3宏间接定义;
3、sys_init_module()源码
/*
*umod: ko文件映射到内存中的地址
*len: ko文件的长度
*uargs: insmod命令加载驱动时的传参
*备注:函数在kernel/module.c中定义,函数被insmod命令调用并传参
*/
SYSCALL_DEFINE3(init_module, void __user *, umod,
unsigned long, len, const char __user *, uargs)
{
struct module *mod;
int ret = 0;
/* Must have permission */
if (!capable(CAP_SYS_MODULE) || modules_disabled)
return -EPERM;
/* Do all the hard work */
mod = load_module(umod, len, uargs);
if (IS_ERR(mod))
return PTR_ERR(mod);
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_COMING, mod);
do_mod_ctors(mod);
/* Start the module */
if (mod->init != NULL)
ret = do_one_initcall(mod->init); //执行模块的加载函数
if (ret < 0) {
/* Init routine failed: abort. Try to protect us from
buggy refcounters. */
mod->state = MODULE_STATE_GOING;
synchronize_sched();
module_put(mod);
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_GOING, mod);
free_module(mod);
wake_up(&module_wq);
return ret;
}
if (ret > 0) {
printk(KERN_WARNING
"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
"%s: loading module anyway...\n",
__func__, mod->name, ret,
__func__);
dump_stack();
}
/* Now it's a first class citizen! Wake up anyone waiting for it. */
mod->state = MODULE_STATE_LIVE;
wake_up(&module_wq);
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_LIVE, mod);
/* We need to finish all async code before the module init sequence is done */
async_synchronize_full();
mutex_lock(&module_mutex);
/* Drop initial reference. */
module_put(mod);
trim_init_extable(mod);
#ifdef CONFIG_KALLSYMS
mod->num_symtab = mod->core_num_syms;
mod->symtab = mod->core_symtab;
mod->strtab = mod->core_strtab;
#endif
module_free(mod, mod->module_init);
mod->module_init = NULL;
mod->init_size = 0;
mod->init_text_size = 0;
mutex_unlock(&module_mutex);
return 0;
}
(1)do_one_initcall(mod->init):这里就是执行驱动加载函数,mod->init是指向module_init宏指定的驱动加载函数的函数指针;具体细节参考博客:《编译驱动的Makefile详解》;
(2)load_module():在函数内部会将描述驱动的struct module结构体注册到全局变量modules中;
5、sys_init_module()函数的引用
//绑定
//include/asm-generic/unistd.h
#define __NR_init_module 105
__SYSCALL(__NR_init_module, sys_init_module)
//调用sys_init_module()
syscall(__NR_init_module, mod, len, opts)
(1)__SYSCALL()的作用相当于绑定,将__NR_init_module和sys_init_module()进行绑定,将来在syscall()调用时进行映射;
(2)sys_init_module()不是像平常的函数一样直接通过函数名进行调用,需要通过syscall()函数进行间接调用,其中第一个参数__NR_init_module就是指定调用sys_init_module()函数;
备注:__SYSCALL()和sysycall()之间如何映射,这里并没有详细分析,__SYSCALL前面已经有两根下划线,说明这个函数已经是内核的核心代码,暂时没必要深入了解。