购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.3 函数:__print_symbol()

文件包含:


#include <linux/kallsyms.h>

函数定义:

在内核源码中的位置:linux-3.19.3/kernel/kallsyms.c

函数定义格式:void__print_symbol(const char*fmt,unsigned long address)

函数功能描述:

该函数的功能与sprint_symbol()的函数功能是相似的(见本章中sprint_symbol()函数的分析),实际上,__print_symbol()函数的实现中调用了函数sprint_symbol()。

该函数根据一个内存中的地址address查找一个内核符号,并将该符号的基本信息,例如符号名name、它在内核符号表中的偏移offset和大小size、所属的模块名(如果有的话)等信息以格式化串fmt的形式输出。而sprint_symbol()函数则是将这些信息放到文本缓冲区buffer中。

输入参数说明:

fmt:输出内核符号基本信息所依据的格式串,由于符号信息是连接成一个字符串的(见本章中sprint_symbol()函数的分析),因此fmt格式化串中一般包含一个“%s”。

address:内核符号中的某一地址,为输入型参数。

返回参数说明:

该函数无返回值。

实例解析:

编写测试文件:__print_symbol.c

头文件及全局变量声明如下:


#include <linux/module.h>
#include <linux/init.h>
#include <linux/kallsyms.h>
MODULE_LICENSE("GPL"); 
static int __init __print_symbol_init(void); 
static void __exit __print_symbol_exit(void);
// 符号a_symbol
int a_symbol(void)                        // 此处void必须添加
{
    return 1;
}
EXPORT_SYMBOL(a_symbol);

模块初始化函数:


int __init __print_symbol_init(void) 
{ 
    char * fmt;                           // 格式化字符串
    unsigned long address;                // 表示符号地址
    char * name;                          // 模块名字
    struct module * fmodule = NULL;       // 指向一个模块的指针
    address = (unsigned long) __builtin_return_address(0);          // 当前函数的返回地址
    fmt = "it's the first part,\n %s";
    __print_symbol(fmt , address );
    printk("\n\n");
    name = "psmouse"; // 可以通过命令lsmod查看当前内核模块,然后选择一个
    fmodule = find_module( name );        // 查找模块名为“psmouse”的模块
    if( fmodule != NULL )
    {
        printk("fmodule->name: %s\n",fmodule->name);
        /* 将模块的内存起始地址赋值给 address */
        address = (unsigned long)fmodule->module_core;   
        fmt = "it's the second part,\n %s";
        __print_symbol(fmt , address );
    }
    printk("\n\n");
    /*将当前模块中符号 a_symbol 的地址加上偏移量 5 赋值给 address */
    address = (unsigned long)a_symbol + 5;  
    fmt = "it's the third part,\n %s";
    __print_symbol(fmt , address );        
    printk("\n\n");
    return 0; 
}

模块退出函数:


void __exit __print_symbol_exit(void) 
{ 
    printk("module exit ok!\n"); 
}

模块初始化及退出函数调用:


module_init(__print_symbol_init); 
module_exit(__print_symbol_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod__print_symbol.ko插入模块,然后执行命令dmesg-c,会出现如图2-4所示的结果。

图2-4 插入__print_symbol模块后系统输出信息

结果分析:

测试程序中调用了find_module()内核函数,它的功能是根据所给的模块名字来获得模块描述符指针的,关于其详细说明见本章中该函数的分析。

关于图2-4所示输出信息内容的说明请参考本章sprint_symbol()函数的分析。

格式化串赋值如fmt="it's the first part,\n%s",其类似于C语言中的printf()函数的第一个参数。调用__print_symbol(fmt,address),根据address查找特定符号的基本信息,先把信息存放到文本缓冲区buffer中,然后以格式化串fmt的形式输出。 FhM2DsFgQudTyJOc86Dylvq4t7miowHlsqUznWLlf0gB0aGfYlUSKHWODRETOOew

点击中间区域
呼出菜单
上一章
目录
下一章
×