您的位置:首页 > 其它

模块API之symbol_put_addr

2017-11-16 08:45 134 查看
void symbol_put_addr(void *addr)的作用是根据addr找到所在的模块,然后将模块的应用计数减1
这里有假定addr是一个函数的地址。
其源码如下:
/* Note this assumes addr is a function, which it currently always is. */
void symbol_put_addr(void *addr)
{
struct module *modaddr;
//将addr由void 类型转为unsigned long,这里的dereference_function_descriptor 是函数,只是说明addr 必须是函数的地址
unsigned long a = (unsigned long)dereference_function_descriptor(addr);
//看地址a是否在kernel的text 段,如果是的话,就不是模块symbol了,就没有必要再查找这个地址对应的模块了
if (core_kernel_text(a))
return;

/*
* Even though we hold a reference on the module; we still need to
* disable preemption in order to safely traverse the data structure.
*/
preempt_disable();
//根据地址a找到对应的模块modaddr,然后调用module_put 将模块的引用计数减1
modaddr = __module_text_address(a);
BUG_ON(!modaddr);
module_put(modaddr);
preempt_enable();
}
看看dereference_function_descriptor的实现
/* function descriptor handling (if any).  Override
* in asm/sections.h */
#ifndef dereference_function_descriptor
#define dereference_function_descriptor(p) (p)
#endif

看看如何通过core_kernel_text 判断地址在kernel的text 段
static inline int init_kernel_text(unsigned long addr)
{
if (addr >= (unsigned long)_sinittext &&
addr < (unsigned long)_einittext)
return 1;
return 0;
}

int notrace core_kernel_text(unsigned long addr)
{
if (addr >= (unsigned long)_stext &&
addr < (unsigned long)_etext)
return 1;

if (system_state < SYSTEM_RUNNING &&
init_kernel_text(addr))
return 1;
return 0;
}
可见只要地址在_stext~_etext,或者当kernel还在没有runing起来的时候在_sinittext~_einittext。
这两个范围就算地址是在kernel的text段。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: