本章节笔记主要理解内核模块代码框架和原理,分析一个简单的内核模块例子。
须要明确的是模块和驱动是两回事。html
内核,是一个操做系统的核心。是基于硬件的第一层软件扩充,提供操做系统的最基本的功能, 是操做系统工做的基础,决定着整个操做系统的性能和稳定性。
内核按照体系结构分为:微内核和宏内核。linux
提升系统灵活性,在调试驱动的时候不须要从新编译内核,也不须要从新启动内核,只须要插入须要调试的驱动便可。
内核模块的特色:框架
内核模块编译后会获得一个 .ko 的 ELF 文件。(ELF 文件能够百度一下,也能够参考野火的内核模块章节。)
ELF 文件:这类文件包含了代码和数据,能够被用来连接成可执行文件或共享目标文件,静态连接库也能够归为这一类。函数
必须内容可分为如下几点:性能
非必须内容:ui
hello_module.c操作系统
/** @file hello_module.c * @brief 简要说明 * @details 详细说明 * @author lzm * @date 2021-02-21 18:08:07 * @version v1.0 * @copyright Copyright By lizhuming, All Rights Reserved * ********************************************************** * @LOG 修改日志: ********************************************************** */ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> // 入口函数:安装驱动时调用的函数 static int __init hello_init(void) { printk(KERN_EMERG "[ KERN_EMERG ] Hello Module Init\n"); printk( "[ default ] Hello Module Init\n"); return 0; } // 出口函数:卸载驱动时调用的函数 static void __exit hello_exit(void) { printk("[ default ] Hello Module Exit\n"); } module_init(hello_init); module_exit(hello_exit); //MODULE_LICENSE("GPL2"); MODULE_AUTHOR("embedfire "); MODULE_DESCRIPTION("hello world module"); MODULE_ALIAS("test_module");
insmod:插入模块:insmod+模块完整路径
。
modprobe:插入模块,insmod具有一样的功能,一样能够将模块加载到内核中,除此之外modprobe还能检查模块之间的依赖关系, 而且按照顺序加载这些依赖,能够理解为按照顺序屡次执行insmod。
depmod:建立模块依赖文件。modprobe是怎么知道一个给定模块所依赖的其余的模块呢?在这个过程当中,depmod起到了决定性做用,当执行modprobe时, 它会在模块的安装目录下搜索module.dep文件,这是depmod建立的模块依赖关系的文件。
rmmod:删除模块:insmod+模块名称
。
lsmod:查看全部模块。
modinfo:显示模块中的几个宏的定义。如协议、做者等等。指针
让系统自动加载模块须要用到命令depmod和modprobe。调试
首先须要将咱们想要自动加载的模块统一放到 /lib/modules/内核版本 目录下,内核版本使用 uname -r
查询;
其次使用depmod创建模块之间的依赖关系,命令 depmod -a
;
这个时候咱们就能够在modules.dep中看到模块依赖关系,可使用以下命令查看:日志
cat /lib/modules/内核版本/modules.dep | grep calculation
最后在/etc/modules加上咱们本身的模块。
实际上,符号指的就是内核模块中使用 EXPORT_SYMBOL 声明的函数和变量。当模块被装入内核后,它所导出的符号都会记录在公共内核符号表中。可供给其它模块使用。
导出方法:
EXPORT_SYMBOL(name) EXPORT_SYMBOL_GPL(name) // name为要导出的标志
调用方法(例子):
extern int name;
模块参数:模块参数是模块被加载时,能够传值给模块中的参数。
Linux内核提供一个宏来实现模块的参数传递:
#define module_param(name, type, perm) module_param_named(name, name, type, perm) #define module_param_array(name, type, nump, perm) module_param_array_named(name, name, type, nump, perm)
对应用户 | 字符 | 说明 |
---|---|---|
当前用户 | S_IRUSR | 用户具备读权限 |
当前用户 | S_IWUSR | 用户具备写权限 |
当前用户组 | S_IRGRP | 当前用户组的其它用户拥有读权限 |
当前用户组 | S_IWGRP | 当前用户组的其它用户拥有写权限 |
其它用户 | S_IROTH | 其它用户具备读权限 |
其它用户 | S_IWOTH | 其它用户具备写权限 |
模块参数使用示例
模块源码:
static int nameA=0; module_param(nameA,int,0); static bool nameB=0; module_param(nameB,bool,0644);
加载模块后,会在路径 /sys/module/模块名/parameters 下存在以模块参数为名的文件。(注:若文件权限为0,则没法查看该文件,也不会显示在该路径)