函数find_module()用来获得一个指向模块的指针。它是根据给定的模块名字查找模块链表,如果找到一个与给定的模块名字相匹配的模块,则返回该模块的指针。由于一个模块的名字是唯一的且不允许有重名的模块,因此基于模块名查找模块是可行的。
文件包含:#include <linux/module.h>
函数定义
在内核源码中的位置:kernel/module.c
函数定义格式:
struct module *f ind_module(const char *name)
输入参数说明
name:为字符串常量,表示所要查找的模块的名字。
返回参数说明
返回值是一个struct module类型的指针,如果find_module()函数查找模块成功,则返回值指向查找到的名为name的模块,如果查找不成功,则返回NULL。
其中,模块结构体module在内核文件linux-3.19.3/include/linux/module.h中定义,下面对该结构体中的一部分字段进行说明:
struct module{
/* 模块当前的状态,state取值有四种情况:
* MODULE_STATE_LIVE, 指示模块当前正在使用
* MODULE_STATE_COMING, 指示模块正被加载
* MODULE_STATE_GOING, 指示模块正被卸载
* MODULE_STATE_UNFORMED, 指示模块未被设置,未定型
*/
enum module_state state;
/*指向模块链表中的下一个模块 */
struct list_head list;
/*特定的模块名称 */
char name[MODULE_NAME_LEN];
…
…
…
/* 向内核空间导出的符号 */
const struct kernel_symbol *syms; /* 指向模块的符号表,表大小为num_syms */
const unsigned long *crcs;
unsigned int num_syms; /* 模块中符号的个数 */
/*内核参数 */
struct kernel_param *kp;
unsigned int num_kp;
/*基于GPL-only的可移出符号 */
unsigned int num_gpl_syms;
const struct kernel_symbol *gpl_syms;
const unsigned long * gpl_crcs;
…
…
/*异常处理函数表 */
unsigned int num_exentries;
struct exception_table_entry *extable;
/*指向初始化方法的函数指针 */
int (*init)(void);
/* 模块初始化时函数的内存地址 */
void *module_init;
/* 模块的内存起始地址 */
void *module_core;
/*模块目标代码的初始部分和执行部分所占内存空间大小 */
unsigned int init_size, core_size;
/*init和core段中可执行代码所在内存空间的大小 */
unsigned int init_text_size, core_text_size;
/* 模块RO区域大小,包括text+rodata两部分区域 */
unsigned int init_ro_size, core_ro_size;
/*基于特定体系结构的模块值 */
struct mod_arch_specific arch;
/* 标识内核是否加入了非自由软件的模块 */
unsigned int taints;
…
…
…
#ifdef CONFIG_SMP
/*每CPU数据 */
void *percpu;
unsigned int percpu_size;
#endif
…
…
#ifdef CONFIG_MODULE_UNLOAD
/* 所有依赖于该模块的模块 */
struct list_head source_list;
/* 所有该模块依赖的模块 */
struct list_head target_list;
/* 模块退出时调用的函数 */
void (*exit)(void);
atomic_t refcnt; //记录模块被引用的次数
#endif
#ifdef CONFIG_CONSTRUCTORS
/*构造函数*/
ctor_fn_t *ctors;
unsigned int num_ctors; //记录模块构造函数个数
#endif};
实例解析
编写测试文件:f ind_module.c
头文件及全局变量声明如下:
#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
static int __init find_module_init(void);
static void __exit find_module_exit(void);
模块初始化函数:
int __init find_module_init(void){
const char * name = "test_module"; //定义待查找的模块名为“test_module”
struct module * fmodule = find_module( name ); //调用查找模块函数
/* 如果查找成功,则输出该模块的信息 */
if( fmodule ! = NULL )
{
printk("fmodule->name: %s\n", fmodule->name); //输出模块名
printk("fmodule->state: %d\n", fmodule->state); //输出模块状态
/* 输出模块core段所占空间大小 */
printk("fmodule->core_size: %d\n", fmodule->core_size);
/* 输出模块引用计数 */
printk("module_refcount(fmodule): %d\n", module_refcount(fmodule));
}
name = "cuse"; //模块名
fmodule = find_module( name ); //调用查找模块函数
/* 如果查找成功,则输出该模块的信息 */
if( fmodule ! = NULL )
{
printk("fmodule->name: %s\n", fmodule->name); //输出模块名
printk("fmodule->state: %d\n", fmodule->state); //输出模块状态
/* 输出模块core段所占空间大小 */
printk("fmodule->core_size: %d\n", fmodule->core_size);
/* 输出模块引用计数 */
printk("module_refcount(fmodule): %d\n", module_refcount(fmodule));
}
return 0;
}
模块退出函数:
void __exit find_module_exit(void){
printk("module exit ok! \n");
}
模块初始化及退出函数调用:
module_init(find_module_init);
module_exit(find_module_exit);