Linux内核API __module_address

__module_address函数功能描述:函数__module_address( )根据给定的一个内存地址addr,获得该内存地址所在的模块。

__module_address文件包含

#include <linux/module.h>

__module_address函数

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

函数定义格式:

struct module *__module_address(unsigned long addr)

__module_address输入参数说明

addr:其值表示内存地址。

__module_address返回参数说明

如果内存地址addr在某一模块的地址空间中,则返回指向该模块的结构体指针,否则返回NULL。

__module_address实例解析

编写测试文件:__module_address.c

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

#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
static int __init __module_address_init(void);
static void __exit __module_address_exit(void);

模块初始化函数:

int a_module(void) //此处定义一个自己添加的内核函数,函数参数必须写入void
{
    return 0;
}
int __init __module_address_init(void)
{
    struct module * ret ;                                   //用于接收测试函数返回值
    unsigned long addr = (unsigned long)a_module;            //得到内核符号a_module的地址
    /*调用__module_address( )函数之前,必须禁止中断,以防止模块在执行操作期间被释放*/
    preempt_disable( );    //禁止抢占
    ret = __module_address(addr) ;
    preempt_enable( );    //允许抢占
    /* 如果返回不为空,则输出该模块的信息 */
    if( ret ! = NULL )
    {
        printk("ret->name: %s\n", ret->name);               //输出模块名
        printk("ret->state: %d\n", ret->state);             //输出模块状态
        printk("ret->core_size: %d\n", ret->core_size);     //输出模块core段所占空间大小
        printk("refs of %s is %d \n", ret->name, module_refcount(ret));
        // 输出模块引用计数
    }
    else
    {
        printk("__module_address return NULL ! \n");
    }
    return 0;
}

模块退出函数:

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

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

module_init(__module_address_init);
module_exit(__module_address_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod __module_address.ko插入模块,然后执行命令dmesg -c,出现如图所示的结果。
Linux内核API __module_address

结果分析:

在该测试程序中,首先令函数__module_address()的参数addr取值为函数a_module()的入口地址,显然addr所表示的内存地址在待加载模块__module_address中。

然后调用__module_address()函数,为了防止模块被释放,需要禁止抢占,宏preempt_disable()和preempt_enable()分别用来实现禁止内核抢占和允许内核抢占。如果查找到内存地址addr所属的模块,则输出该模块的name、state等信息。由上图中的输出信息可知,ret->name恰为“__module_address”, ret->state为1(即表示该模块处于正在被加载的MODULE_STATE_COMING状态,见下面关于枚举类型module_state的说明), ret->core_size为12469字节,然后调用module_refcount()得到该模块的引用计数为1。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程