内核中驱动加载函数(sys_init_module)详解

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前面已经有两根下划线,说明这个函数已经是内核的核心代码,暂时没必要深入了解。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值