概述
//给一个给定的addr,要是这个addr在某个模块的【地址空间】中,则返回指向该模块的指针
struct module *__module_address(unsigned long addr)
{
struct module *mod;
if (addr < module_addr_min || addr > module_addr_max)
return NULL;
list_for_each_entry_rcu(mod, &modules, list) {
if (mod->state == MODULE_STATE_UNFORMED)
continue;
if (within_module(addr, mod))
return mod;
}
return NULL;
}
//给一个给定的addr,要是这个addr在某个模块的【text段,也就是代码段】中,则返回指向该模块的
//指针
struct module *__module_text_address(unsigned long addr)
{
struct module *mod = __module_address(addr);
if (mod) {
/* Make sure it's within the text section. */
if (!within(addr, mod->module_init, mod->init_text_size)
&& !within(addr, mod->module_core, mod->core_text_size))
mod = NULL;
}
return mod;
}
//【内核符号表】,就是在内核的内部函数或变量中,可供外部引用的函数和变量的符号表。
//其实说白了就是一个索引文件,它存在的目的就是让外部软件可以知道kernel文件内部实际分配的位置。
//给一个内存地址address,查找一个内核符号,并将该符号的基本信息,符号名name,偏移offset
//大小size,所属模块名,保存在 fmt 的%s中
void __print_symbol(const char *fmt, unsigned long address)
{
char buffer[KSYM_SYMBOL_LEN];
sprint_symbol(buffer, address);
printk(fmt, buffer);
}
static int __sprint_symbol(char *buffer, unsigned long address,
int symbol_offset, int add_offset)
{
char *modname;
const char *name;
unsigned long offset, size;
int len;
address += symbol_offset;
name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
if (!name)
return sprintf(buffer, "0x%lx", address - symbol_offset);
if (name != buffer)
strcpy(buffer, name);
len = strlen(buffer);
offset -= symbol_offset;
if (add_offset)
len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
if (modname)
len += sprintf(buffer + len, " [%s]", modname);
return len;
}
//给一个内核符号名symbol,获得该符号的内存地址,找到其所在的内核模块,并会给该模块的引用计数
//加1
void *__symbol_get(const char *symbol)
{
struct module *owner;
const struct kernel_symbol *sym;
preempt_disable();
sym = find_symbol(symbol, &owner, NULL, true, true);
if (sym && strong_try_module_get(owner))
sym = NULL;
preempt_enable();
return sym ? (void *)sym->value : NULL;
}
//给一个内核符号名symbol,获得该符号的内存地址,找到其所在的内核模块,并会给该模块的引用计数
//减1 【此处即是内核态下,部分API成双成对的使用,有+就要有-】
void __symbol_put(const char *symbol)
{
struct module *owner;
preempt_disable(); //禁止抢占
if (!find_symbol(symbol, &owner, NULL, true, false))
BUG();
module_put(owner);
preempt_enable();
}
最后
以上就是耍酷帽子为你收集整理的一些内核模块函数(1)的全部内容,希望文章能够帮你解决一些内核模块函数(1)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复