模块API之try_module_get

来源:互联网 发布:热血江湖自动登录源码 编辑:程序博客网 时间:2024/05/30 23:43
try_module_get的作用是如果一个模块处于活动状态,则对其引用计数加1.在kernel中使用的例程如下:struct file *anon_inode_getfile(const char *name,const struct file_operations *fops,void *priv, int flags){struct qstr this;struct path path;struct file *file;if (IS_ERR(anon_inode_inode))return ERR_PTR(-ENODEV);if (fops->owner && !try_module_get(fops->owner))return ERR_PTR(-ENOENT);}其源码如下:bool try_module_get(struct module *module){bool ret = true;//首先这个模块不能为nullif (module) {// 由于要增加模块的引用计数,因此需要通过preempt_disable()/preempt_enable()来禁止内核抢占preempt_disable();/* Note: here, we can fail to get a reference */// 首先通过module_is_live 判读模块处于活动状态,这个函数其实就是判断模块的flag是否是MODULE_STATE_GOING。然后通过atomic_inc_not_zero来增加模块的引用计数if (likely(module_is_live(module) &&   atomic_inc_not_zero(&module->refcnt) != 0))trace_module_get(module, _RET_IP_);elseret = false;preempt_enable();}return ret;}我们来看看atomic_inc_not_zero的实现#ifndef atomic_inc_not_zero#define atomic_inc_not_zero(v)atomic_add_unless((v), 1, 0)#endif继续看atomic_add_unlessstatic inline int atomic_add_unless(atomic_t *v, int a, int u){return __atomic_add_unless(v, a, u) != u;}替换一下等于调用__atomic_add_unless(v, 1, 0) != 0;其源码如下:#ifndef __atomic_add_unlessstatic inline int __atomic_add_unless(atomic_t *v, int a, int u){int c, old;//首先读取v这个地址里面的值,首先v这个地址里面的值不能是u,这里u等于0,因为前面已经判断过模块是活动的,因此这c肯定不等于0// 然后调用atomic_cmpxchgc = atomic_read(v);while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)c = old;return c;}#endif#define atomic_cmpxchg(v, old, new)(cmpxchg(&((v)->counter), (old), (new)))#ifndef cmpxchg64_local#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))#endif#define cmpxchg(ptr, o, n)cmpxchg_local((ptr), (o), (n))static inline u64 __cmpxchg64_local_generic(volatile void *ptr,u64 old, u64 new){u64 prev;unsigned long flags;raw_local_irq_save(flags);prev = *(u64 *)ptr;if (prev == old)*(u64 *)ptr = new;raw_local_irq_restore(flags);return prev;}原来__cmpxchg64_local_generic的作用首先读取ptr这个地址里面的值,如果这个值等于old,就给ptr 赋值为new,但是返回ptr之前的旧值old回到__atomic_add_unless 中的atomic_cmpxchg,就是先读取v里面的值,如果值等于1的话,这时c就等于1,然后给v加1,这个时候v里面的值是2,返回c的值,也就是1最后总结一下:static inline int atomic_add_unless(atomic_t *v, int a, int u){return __atomic_add_unless(v, a, u) != u;}可以简单的认为: @a to @v, so long as @v was not already @u.Returns non-zero if @v was not @u, and zero otherwise.也就是返回非零表示v已经加上a了.

原创粉丝点击