一些内核模块函数(1)

//给一个给定的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();
}

猜你喜欢

转载自blog.csdn.net/dummkopfer/article/details/80377987
今日推荐