2.1 函数:__module_address( )
文件包含:
#include <linux/module.h>
函数定义:
在内核源码中的位置:linux-3.19.3/kernel/module.c
函数定义格式:struct module *__module_address(unsigned long addr)
函数功能描述:
函数__module_address( )根据给定的一个内存地址addr,获得该内存地址所在的模块。
输入参数说明:
addr:其值表示内存地址。
返回参数说明:
如果内存地址addr在某一模块的地址空间中,则返回指向该模块的结构体指针,否则返回NULL。其中关于结构体struct module的定义见本章中关于f ind_module( )函数的分析。
实例解析:
编写测试文件:__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,出现如图2-1所示的结果。
图2-1 插入__module_address模块后系统输出信息
结果分析:
在该测试程序中,首先令函数__module_address ( )的参数addr取值为函数a_module( )的入口地址,显然addr所表示的内存地址在待加载模块__module_address中。
然后调用__module_address ( )函数,为了防止模块被释放,需要禁止抢占,宏preempt_disable( )和preempt_enable( )分别用来实现禁止内核抢占和允许内核抢占。如果查找到内存地址addr所属的模块,则输出该模块的name、state等信息。由图2-1中的输出信息可知,ret->name恰为“__module_address”, ret->state为1(即表示该模块处于正在被加载的MODULE_STATE_COMING状态,见下面关于枚举类型module_state的说明), ret->core_size为12469字节,然后调用module_refcount( )得到该模块的引用计数为1。
分析中涉及了枚举类型module_state,它定义了模块的三种状态,其具体定义请参见本章中关于函数f ind_module( )的分析。函数module_refcount( )的功能是得到模块的引用计数,具体请见本章中该函数的分析。