try_module_get:功能:判断module模块是否处于活动状态,然后通过local_inc()宏将该模块的引用计数加1
static inline int try_module_get(struct module *module)
{
int ret = 1;
if (module) {
unsigned int cpu = get_cpu();
if (likely(module_is_live(module))) {
local_inc(__module_ref_addr(module, cpu));
trace_module_get(module, _THIS_IP_,
local_read(__module_ref_addr(module, cpu)));
}
else
ret = 0;
put_cpu();
}
return ret;
}
module_put:功能:使指定的模块使用量减一
void module_put(struct module *module)
{
if (module) {
unsigned int cpu = get_cpu();
local_dec(__module_ref_addr(module, cpu));
/* Maybe they're waiting for us to drop reference? */
if (unlikely(!module_is_live(module)))
wake_up_process(module->waiter);
put_cpu();
}
}
使用例子:
增加引用计数,在卸载模块之前,如果该模块的计数不为0,就会卸载失败
static int
fb_open(struct inode *inode, struct file *file)
__acquires(&info->lock)
__releases(&info->lock)
{
int fbidx = iminor(inode);
struct fb_info *info;
int res = 0;
if (fbidx >= FB_MAX)
return -ENODEV;
info = registered_fb[fbidx];
if (!info)
request_module("fb%d", fbidx);
info = registered_fb[fbidx];
if (!info)
return -ENODEV;
mutex_lock(&info->lock);
//增加引用计数,在卸载模块之前,如果该模块的计数不为0,就会卸载失败
if (!try_module_get(info->fbops->owner)) {
res = -ENODEV;
goto out;
}
file->private_data = info;
if (info->fbops->fb_open) {
res = info->fbops->fb_open(info,1);
if (res)
module_put(info->fbops->owner);
}
#ifdef CONFIG_FB_DEFERRED_IO
if (info->fbdefio)
fb_deferred_io_open(info, inode, file);
#endif
out:
mutex_unlock(&info->lock);
return res;
}
如果卸载一个模块,使模块引用计数减少1要在module_exit函数之前调用,一般在release函数调用,这是用户空间close函数的系统调用。
static int
fb_release(struct inode *inode, struct file *file)
__acquires(&info->lock)
__releases(&info->lock)
{
struct fb_info * const info = file->private_data;
mutex_lock(&info->lock);
if (info->fbops->fb_release)
info->fbops->fb_release(info,1);
module_put(info->fbops->owner);
mutex_unlock(&info->lock);
return 0;
}