linux查询内核模块api,模块机制 – Linux内核API find_module

find_module函数功能描述:函数find_module()用来获得一个指向模块的指针。它是根据给定的模块名字查找模块链表,如果找到一个与给定的模块名字相匹配的模块,则返回该模块的指针。由于一个模块的名字是唯一的且不允许有重名的模块,因此基于模块名查找模块是可行的。

find_module文件包含

#include

find_module函数定义

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

函数定义格式:

struct module *f ind_module(const char *name)

find_module输入参数说明

name:为字符串常量,表示所要查找的模块的名字。

find_module返回参数说明

返回值是一个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

};

find_module实例解析

编写测试文件:f ind_module.c

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

#include

#include

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);

实例运行结果及分析:

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

e271165cb61c8af2a8a50479cbf50b25.png

结果分析:

在该测试程序中,调用find_module()内核函数查找了两个内核模块。

首先查找名为“test_module”的模块,将name赋值为“test_module”,然后调用f ind_module( )来获得与它相对应的模块的结构体描述符指针,赋值给fmodule。通过输出结构体指针fmodule的一些字段来获得模块“test_module”的一些信息,由输出信息可知:fmodule->name恰为“test_module”, fmodule->state为0(即表示该模块处于正在被使用的MODULE_STATE_LIVE状态,见下面关于枚举类型module_state的说明), fmodule->core_size恰为12950字节,然后调用module_refcount( )得到该模块的引用计数为5。

同样的,再将name赋值为“cuse”,调用find_module()来获得与它相对应的模块的结构体描述符指针,赋值给fmodule。由输出信息可知:fmodule->name恰为“cuse”, fmodule->state为0(即表示该模块处于正在被使用的MODULE_STATE_LIVE状态), fmodule->core_size恰为13445,然后调用module_refcount( )得到该模块的引用计数为3。

为了验证上述结果的正确性,这里截取了模块显示列表中的一些信息,如图所示。

ad45d56532ca9ac5a830dc6eabaaa9ff.png

从上图中可以看到,系统中存在两个名为“test_module”和“cuse”的模块,它们的大小和引用计数都显示出来,与上面测试的结果是一致的。

分析中涉及枚举类型module_state,它在内核文件linux-3.19.3/include/linux/module.h中定义,该枚举类型定义了模块的四种状态,其具体定义如下:

enum module_state

{

MODULE_STATE_LIVE, //模块当前正在使用

MODULE_STATE_COMING, //模块正被加载

MODULE_STATE_GOING, //模块正被卸载

MODULE_STATE_UNFORMED, //模块未被设置,未定型

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值