【linux驱动】详细剖析第一个hello word驱动程序

发布时间:2024年01月20日

驱动程序的框架

Linux 驱动的基本框架主要由模块加载函数,模块卸载函数,模块许可证声明,模块参数,模块导出符号,模块作者信息等几部分组成,其中模块参数,模块导出符号,模块作者信息是可选的部分,也就是可要可不要。剩余部分是必须有的。

模块加载函数
当加载驱动模块时,内核会通过module_init(xxx_init);执行模块加载函数,完成模块加载函数中的初始化工作。一般模块加载函数形式如下:

static int __init xxx_init(void)
{
	//驱动加载需要完成的任务
	
	return 0;
}

其中xxx处可添加独有的函数名,而后面的_init是不能够更改的,函数参数也不用更改。

模块卸载函数
卸载某模块时,内核会通过module_exit(xxx_exit);执行模块卸载函数,完成模块卸载函数中的退出工作。卸载驱动模块的函数原型如下:

//驱动的出口函数
static void __exit xxx_exit(void)
{
	// 做卸载需要完成的任务	
		
}

与驱动加载一样,其中xxx处可添加独有的函数名,而后面的_exit是不能够更改的,函数参数也不用更改。

模块许可证声明

许可证声明描述了内核模块的许可权限,如果不声明模块许可,模块在加载的时候,会收到“内核被污染(kernel tainted)”的警告。可接受的内核模块声明许可包括GPLGPL v2。具体设置驱动的许可声明可使用函数MODULE_LICENSE(“GPL v2”);,函数参数为许可类型。

模块参数
模块参数是指模块被加载的时候传递给模块的值。通常使用函数:

  • module_param_array(name, type, nump, perm):传递数组给内核
  • module_param_string(name, string, len, perm):传递字符串给内核
  • module_param(name, type, perm):传递单个参数给内核

完成参数传递。详细说明可见此文

模块导出符号
内核模块可以导出的符号,如果导出,其他模块可以使用本模块中的变量或函数。通常使用EXPORT_SYMBOL()函数导出变量或者函数。

模块作者信息
作者信息主要说明该模块是谁创作的,可使用函数 MODULE_AUTHOR(“zxj”);来指明,其中参数就是作者。

除此之外,还可以使用MODULE_DESCRIPTION()函数通过传入参数描述驱动。

驱动程序的使用示例

下面的驱动是一个最佳单的驱动源码,能够完成在加载驱动时打印“hello word”,在卸载驱动时打印“baibai”

#include <linux/module.h>
#include <linux/kernel.h>

// 驱动的入口函数
static int __init hello_init(void)
{
	printk(KERN_EMERG"hello word!\r\n");

	return 0;
}

//驱动的出口函数
static void __exit hello_exit(void)
{
	printk(KERN_EMERG"baibai\r\n");
}


module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("zxj");
MODULE_DESCRIPTION("output hello when insmod ;output baibai when rmmod");

其中,printk()函数用于内核打印数据,而函数参数中的KERN_EMERG用来描述打印信息的优先级。

在将内核编译完成生成的.ko文件上传到开发板后:

  • 通过insmod + 驱动名.ko可加载驱动到内核。

  • 通过lsmod可查看当前已经加载成功的驱动。

  • 通过ls /dev/设备名可查看驱动加载成功后创建的设备名。

  • 通过rmmod + 驱动名可卸载驱动。

驱动加载卸载后的执行结果如下:

在这里插入图片描述

此处需要注意,加载驱动时驱动名后面需要加上.ko,而卸载驱动时直接是驱动名即可,不需要加后缀。

文章来源:https://blog.csdn.net/qq_53960242/article/details/135568829
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。