一些内核模块函数(3)

//查看模块 mod 是否处于活跃状态
static inline int module_is_live(struct module *mod)
{
return mod->state != MODULE_STATE_GOING;
}


//模块引用计数减1,因为内核卸载某些模块时,要保证这个模块的引用计数为0,所以可以一次或反复
//调用这个函数,实现模块的引用计数清0,从而卸载
void module_put(struct module *module)
{
int ret;


if (module) {
preempt_disable();
ret = atomic_dec_if_positive(&module->refcnt);
WARN_ON(ret < 0); /* Failed to put refcount */
trace_module_put(module, _RET_IP_);
preempt_enable();
}
}


//获得一个模块的引用计数,方便卸载时知道用多少次 module_put
/* MODULE_REF_BASE is the base reference count by kmodule loader. */
#define MODULE_REF_BASE 1
int module_refcount(struct module *mod)
{
return atomic_read(&mod->refcnt) - MODULE_REF_BASE;
}


//给一个内存地址addr,找到该地址所在的模块后,将模块的引用计数减1,内部调用了 module_put
void symbol_put_addr(void *addr)
{
struct module *modaddr;
unsigned long a = (unsigned long)dereference_function_descriptor(addr);


if (core_kernel_text(a))
return;


/* module_text_address is safe here: we're supposed to have reference
* to module from symbol_get, so it can't go away. */
modaddr = __module_text_address(a);
BUG_ON(!modaddr);
module_put(modaddr);
}


//给一个模块module,看是否处于活跃状态,然后将该模块module的引用计数加1
bool try_module_get(struct module *module)
{
bool ret = true;


if (module) {
preempt_disable();
/* Note: here, we can fail to get a reference */
if (likely(module_is_live(module) &&
   atomic_inc_not_zero(&module->refcnt) != 0))
trace_module_get(module, _RET_IP_);
else
ret = false;


preempt_enable();
}
return ret;
}

猜你喜欢

转载自blog.csdn.net/Dummkopfer/article/details/80380264
今日推荐