文章目录
一个最简单的驱动模块
驱动编译的Makefile
相关命令
错误解决:
点击下方阅读原文可访问文中超链接
一个最简单的驱动模块
一个精简的驱动模块可以只有不到10行的内容,如下是一个简单的测试程序。
#include <linux/init.h>
#include <linux/module.h>
#define DEBUG(fmt, ...) \
do{ \
if(if_debug) \
printk(KERN_INFO "DEBUG > " fmt, ##__VA_ARGS__); \
}while(0)
bool if_debug = false;
/*定义一个bool类型的变量,作为一个模块入参,在装载模块时可赋值*/
module_param(if_debug, bool, S_IRUSR);
static int __init test_init(void)
{
DEBUG("%s\r\n",__FUNCTION__);
return 0;
}
static void __exit test_exit(void)
{
DEBUG("%s\r\n",__FUNCTION__);
}
/*此宏声明内核模块的初始化入口点*/
module_init(test_init);
/*此宏声明内核模块的退出入口点*/
module_exit(test_exit);
/*声明开源协议*/
MODULE_LICENSE("GPL");
/*声明作者*/
MODULE_AUTHOR("wei");
/*声明模块的描述*/
MODULE_DESCRIPTION("this is a test driver");
其中module_param用以定义一个内核模块参数,可在装载(如insmod)模块时赋值,name表示变量名;type表示变量类型,目前支持有byte, short, ushort, int, uint, long, ulong,charp(字符指针),bool,invbool(和bool逻辑相反);perm表示在sysfs文件系统中该变量的权限,与文件的权限一致,可查看open接口的文档查看有哪些权限(注意其不能拥有可执行权限)。装载模块后,可在/sys/module/test/parameters/目录(视具体的驱动名而定)查看定义了哪些参数。
include/linux/moduleparam.h
#define module_param(name, type, perm) \
module_param_named(name, name, type, perm)
# 省掉了可执行权限
S_IRUSR 00400 user has read permission
S_IWUSR 00200 user has write permission
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
module_init声明内核模块的初始化入口点,如果驱动采用编译进内核源码的方式,则在内核启动时运行;如果采用编译成模块的方式,则在驱动加载(如insmod)的时候运行。
module_exit声明内核模块的退出入口点,如果驱动采用编译进内核源码的方式,此函数没有作用;如果采用编译成模块的方式,则在驱动卸载(如rmmod)的时候运行。
include/linux/module.h
#define module_init(x) __initcall(x);
#define module_exit(x) __exitcall(x);
驱动编译的Makefile
下面是一个通用的编译驱动的Makefile,KERNEL_DIR表示内核源码树的位置;obj-m表示生成的目标文件名;-C选项可以改变当前的工作目录,即到内核源码的根目录;M指定要编译的模块源码目录;modules是顶层Makefile里面的伪目标。
KERNEL_DIR=/home/Desktop/s5pv210/linux-5.7.8
obj-m := test.o
all:
# 执行内核源码根目录里面的Makefile的modules伪目标将当前
目录内容编译成内核模块
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean
相关命令
命令 | 描述 |
---|---|
lsmod | 显示当前已加载的驱动模块 |
insmod | 装载驱动模块 |
rmmod | 卸载驱动模块 |
modinfo | 显示驱动模块的相关信息 |
depmod | 检测驱动模块之间的依赖关系 |
modprobe | 也用于加载驱动模块,但会先检测驱动模块之间的依赖关系,依次加载依赖的模块 |
通过前面写的测试模块程序测试如上的相关命令:
modinfo test.ko
# 效果
filename: test.ko
author: wei
description: this is a test driver
license: GPL
depends:
vermagic: 5.7.8 preempt mod_unload ARMv7 p2v8
# 未给内核模块传参
insmod test.ko
# 效果
# 可在/sys/module/目录看到生成了对应的模块目录,也可
# 用dmesg命令查看日志
rmmod test.ko
# 效果
# 可看到/sys/module/目录里面对应的模块目录被移除
# 给内核模块传参
insmod test.ko if_debug=1
# 效果
# 能够输出调试信息
DEBUG > test_init
rmmod test.ko
# 效果
# 能够输出调试信息
DEBUG > test_exit
错误解决:
先在lib目录下创建modules目录,并在modules目录下创建5.7.8(视具体内核版本而定)目录,执行depmod命令,执行完后会在/lib/modules/5.7.8/目录下生成modules.dep.bb文件,然后使用mv命令重命名该文件为modules.dep即可。
modinfo: can't open '/lib/modules/5.7.8/modules.dep': No such file or directory
欢迎扫码关注我的微信公众号