虫虫首页|资源下载|资源专辑|精品软件
登录|注册

您现在的位置是:首页 > 技术阅读 >  笔记:linux驱动开发(1、了解内核模块)

笔记:linux驱动开发(1、了解内核模块)

时间:2024-06-01

文章目录

  • 一个最简单的驱动模块

  • 驱动编译的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

欢迎扫码关注我的微信公众号