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

文章目录

  • 驱动程序的框架
  • 驱动程序的使用示例

驱动程序的框架

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,而卸载驱动时直接是驱动名即可,不需要加后缀。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/336462.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++——vector的使用及其模拟实现

vector的使用及其模拟实现 文章目录 vector的使用及其模拟实现1. vector的使用1.1 构造函数construct1.2 获取当前存储的数据个数size()和最大容量capacity()1.3 访问1.3.1 operator[]运算符重载1.3.2 迭代器访问1.3.3 范围for 1.4 容量相关reserve()和resize()1.5 增&#xff…

【趣味题-04】20240120百鸡百钱(遍历循环排除,类似加减法)

背景需求 题目 5&#xff1a;百鸡百钱 作者&#xff1a;阿夏 时间&#xff1a;2024年1月20日百鸡百钱 公鸡每只 5 元&#xff0c;母鸡每只 3 元&#xff0c;小鸡 3 只一元&#xff0c; 现要求用 100 元钱买 100 只鸡(三种类型的鸡都要买)&#xff0c; 问公鸡、母鸡、小鸡各买几…

Oracle 经典练习题 50 题

文章目录 一 CreateTable二 练习题1 查询"01"课程比"02"课程成绩高的学生的信息及课程分数2 查询"01"课程比"02"课程成绩低的学生的信息及课程分数3 查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩4 查询平均成绩小于…

“加密行业迈向上市潮”!全球第二大稳定币发行商,秘密提交IPO申请!

在过去的15年里&#xff0c;虽然加密行业蓬勃发展&#xff0c;但上市公司的数量却相对稀少。然而&#xff0c;随着加密市场在经济走强的背景下出现反弹&#xff0c;今年区块链领域的投资资金和潜在的IPO似乎均有望迎来转机。 高盛预测&#xff0c;2024年下半年IPO活动将更加活跃…

Red Hat Enterprise Linux 8.9 安装图解

引导和开始安装 选择倒计时结束前&#xff0c;通过键盘上下键选择下图框选项&#xff0c;启动图形化安装过程。需要注意的不同主板默认或者自行配置的固件类型不一致&#xff0c;引导界面有所不同。也就是说使用UEFI和BIOS的安装引导界面是不同的&#xff0c;如图所示。若手动调…

设计一个Key-Value缓存去存储最近的Web Server查询的结果

1: 定义Use Case和约束 Use Cases 我们可以定义如下 Scope: User 发送一个 search request, 缓存命中成功返回DataUser 发送一个 search request, 缓存未命中&#xff0c;未成功返回DataService 有高可用 约束和假设 状态假设 Traffic 分布不是均匀的 热度高的查询总是被…

接口测试遇到500报错?别慌,你的头部可能有点问题

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

class_13:静态成员static关键字

#include <iostream>using namespace std;class Myclass{ public:int datas;static int staticValue; //静态成员变量在类外进行初始化void printInfo(){cout<<datas<<endl;}static int getStaticDatas()//静态成员函数不能直接访问非静态变量和非静态函数&a…

Python sleep函数用法:线程睡眠

如果需要让当前正在执行的线程暂停一段时间&#xff0c;并进入阻塞状态&#xff0c;则可以通过调用 time 模块的 sleep(secs) 函数来实现。该函数可指定一个 secs 参数&#xff0c;用于指定线程阻塞多少秒。 当前线程调用 sleep() 函数进入阻塞状态后&#xff0c;在其睡眠时间…

GPT应用_AutoGPT

项目地址&#xff1a;https://github.com/Significant-Gravitas/AutoGPT 1 功能 1.1 整体功能&#xff0c;想解决什么问题 单独使用 ChatGPT 时&#xff0c;只提供基本的聊天&#xff0c;无法实现复杂多步的功能&#xff0c;以及与其它应用交互&#xff0c;如果想提供某种功…

linux(七):I2C(touch screen)

本文主要探讨210触摸屏驱动相关知识。 I2C子系统 i2c子系统组成部分:I2C核心,I2C总线驱动,I2C设备驱动 I2C核心&#xff1a;I2C总线驱动和设备驱动注册注销方法 I2C总线驱动&#xff1a;I2C适配器(I2C控制器)控制,用于I2C读写时序(I2C_adapter、i2c_a…

2023:既是结束也是开始

2023年注定是不平凡的一年&#xff0c;这一年真的经历了很多事&#xff0c;包括学习、生活、工作等等&#xff0c;上半年忙着毕业以及一些其他的事情&#xff0c;很多挖的坑都没来得及填&#xff0c;下半年研一开学以后终于有了足够的时间学习&#xff0c;接下来就用这篇文章来…

MySQL执行计划全面解析

执行计划 如果不知道执行计划&#xff0c;那就不可能进行SQL优化&#xff0c;那么执行计划是什么呢&#xff1f; 使用explain关键字可以模拟优化器执行SQL查询语句&#xff0c;从而知道MySQL是如何处理你的SQL的&#xff0c;进而分析性能瓶颈 用起来其实很简单&#xff0c;使用…

Swin版VMamba来了!精度再度提升,VMamba-S达成83.5%,超越Swin-S,已开源!

本文首发&#xff1a;AIWalker 就在昨日&#xff0c;华科王兴刚团队公开了Mamba在ViT的入局Vim&#xff0c;取得了更高精度、更快速度、更低显存占用。相关信息可参考&#xff1a; 入局CV&#xff0c;Mamba再显神威&#xff01;华科王兴刚团队首次将Mamba引入ViT&#xff0c;更…

Java 内存模型深度解析

优质博文&#xff1a;IT-BLOG-CN 一、并发编程模型的两个关键问题 【1】并发中常见的两个问题&#xff1a;线程之间如何通信及线程之间如何同步。通信是指线程之间以何种机制来交换信息。在命令式编程中&#xff0c;线程之间的通信机制有两种&#xff1a;内存共享和消息传递&…

Redis 存在线程安全问题吗?为什么?

一个工作了 5 年的粉丝私信我。 他说自己准备了半年时间&#xff0c;想如蚂蚁金服&#xff0c;结果第一面就挂了&#xff0c;非常难过。 问题是&#xff1a; “Redis 存在线程安全问题吗&#xff1f;” 一、问题解析 关于这个问题&#xff0c;我从两个方面来回答。 第一个&a…

ChatGPT 到 Word:使用 Writage 进行复制粘贴魔法

ChatGPT 到 Word&#xff1a;使用 Writage 进行复制粘贴魔法 写在前面Writage的使用 写在前面 随着ChatGPT的日益普及&#xff0c;越来越多的人每天依赖它来完成各种任务。无论是寻找信息、语言翻译、解决数学问题&#xff0c;还是精炼复杂的概念和文本&#xff0c;ChatGPT 都…

AWS CI/CD之二:配置CodeDeploy

问题 前面一篇文章介绍了CodeBuild中构建一个Java的Maven项目。在这个基础上面&#xff0c;我们继续AWS CI/CD工作流构建之路。 1.配置CodePipeline简配版 这里主要是利用CodePipeline配置之前的CodeBuild项目&#xff0c;以便生产出需要部署的jar文件和CodeDeploy需要用到相…

【rust/bevy】使用points构造ConvexMesh

目录 说在前面问题提出Rapier具体实现参考 说在前面 操作系统&#xff1a;win11rust版本&#xff1a;rustc 1.77.0-nightlybevy版本&#xff1a;0.12 问题提出 在three.js中&#xff0c;可以通过使用ConvexGeometry从给定的三维点集合生成凸包(Convex Hull) import { ConvexGeo…

【c++】——栈or队列or优先级队列

目录 &#x1f393;容器适配器 &#x1f393;Stack栈 &#x1f6a9;Stack的介绍 &#x1f6a9;Stack的基本使用 &#x1f6a9;Stack底层实现 &#x1f393;queue队列 &#x1f6a9;queue的介绍 &#x1f6a9;queue的基本使用 &#x1f6a9;queue的底层实现 &#x1…