linux 内核模块学习总结

linux 内核模块学习总结,第1张

文章目录
  • 一、简介
  • 二、一个简单的内核模块代码
  • 三、模块内常用符号说明
  • 四、内核模块加载
    • 1、模块加载函数
    • 2、模块加载
    • 3、查看设备上当前模块的信息
    • 4、查看模块依赖
  • 五、内核模块卸载
    • 1、模块卸载函数
    • 2、模块卸载
  • 六、模块参数
  • 七、导出符号
  • 八、编译

一、简介

linux内核架构庞大功能众多,包含非常多的组件。并不是所有功能都是用户需要的,也不可能稍微修改一些功能就重新全编linux内核。

当前linux使用模块(module)的机制解决这个问题
1、module可以单独编译
2、module可以在内核启动后动态加载或卸载
二、一个简单的内核模块代码
#include 
#include 
#include 

static int __init module_init_test(void)
{
    pr_info("module init test!");
    /* do something about module init */
    pr_info("module init end!");
    return 0;
}

static void __exit module_exit_test(void)
{
    pr_info("module exit test!");
    /* do something about module exit */
    pr_info("module exit end!");
    return;
}


module_init(module_init_test);
module_exit(module_exit_test);

MODULE_AUTHOR("zhuang da shuai ge");
MODULE_DESCRIPTION("just a test module");
MODULE_LICENSE("GPL");
三、模块内常用符号说明
module_init();           /* 模块加载 */   /* 第四章说明 */
module_exit();           /* 模块卸载 */   /* 第五章说明 */
module_param();          /* 模块参数 */     /* 第六章说明 */
EXPORT_SYMBOL();         /* 导出符号 */     /* 第七章说明 */
EXPORT_SYMBOL_GPL();     /* 导出符号 */     /* 第七章说明 */

模块声明相关:
MODULE_AUTHOR("***");        /* 作者 */
MODULE_LICENSE("GPL");       /* 许可证说明 */
MODULE_DESCRIPTION("***");   /* 模块信息 */
MODULE_ALIAS("***");         /* 模块别名 */
MODULE_VERSION("***");       /* 模块版本 */
等
四、内核模块加载 1、模块加载函数

代码中static int __init module_init_test(void)就是一个模块加载函数,一般以__init标识,使用module_init(module_init_test)指定。
模块加载时,实际就是运行此函数。返回整形值,正常返回0,其它异常返回值在中有定义,函数最好按照规范定义返回。

2、模块加载

模块加载有insmod和modprobe两种方式:

insmode ./test.ko
modprobe test

例如:

~# insmod test.ko 
~# dmesg -c
[148348.202699] module init test!
[148348.202699] module init end!

两种模块加载的方法实际都是运行模块加载函数。modprobe功能更加强大,会自动加载模块的依赖。

3、查看设备上当前模块的信息

在linux环境下,使用lsmod可以查看设备上当前已经加载的模块,该命令实际上是解析/proc/modules.

~# lsmod |grep test
test                   16384  0
~# cat /proc/modules |grep test
test 16384 0 - Live 0xffffffffc0336000 (OE)

另外,已加载的模块的信息,也存在/sys/module目录下。
使用modeinfo <模块名> 可以查看模块信息。

~# modinfo test
filename:       /lib/modules/4.19.0-12-2-amd64/extra/test.ko
license:        GPL
description:    just a test module
author:         zhuang da shuai ge
depends:        
retpoline:      Y
name:           test
vermagic:       4.19.0-12-2-amd64 SMP mod_unload modversions 
4、查看模块依赖

参考以前写的文章:查看内核模块依赖关系和动态库依赖关系

五、内核模块卸载 1、模块卸载函数

代码中static void __exit module_exit_test(void)就是一个模块卸载函数,一般以__exit 标识,使用module_exit(module_exit_test)指定。
模块卸载时,实际就是调用此函数。

2、模块卸载
rmmod test
modprobe -f test (卸载模块和其依赖)

模块卸载可直接用rmmod,也可以用modprobe r 模块名 方式,使用modprobe r 会同时卸载相关依赖。

~# rmmod test 
~# dmesg -c
[ 4175.680292] module exit test!
[ 4175.680292] module exit end!
六、模块参数

使用module_param(参数名,参数类型,参数读写权限) 定义模块的参数。例如:

static int test_param = 10;
module_param(test_param, int, S_IGUGO);

如此定义后,加载内核模块时,用户可直接传递模块参数的值:

modprobe(insmod) 模块名 参数名=参数值
modprobe(insmod) test test_param=11

如此加载模块,test_param值则被定义为11。若加载模块时不传递参数值,则test_param为默认值10。

七、导出符号

/proc/kallsyms文件中记录了内核符号表,记录符号以及符号所在的内存地址。在这个符号表中的接口,可被其它模块调用。
模块中可用如下宏将符号导出到内核符号表中,导出的符号可被其它模块使用:

	EXPORT_SYMBOL();
	EXPORT_SYMBOL_GPL();
八、编译
obj-m := modulename.o

模块包含多个文件时:

obj-m := modulename.o
modulename-objs := test1.o test2.o

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/739893.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存