当前位置: 首页 > news >正文

驱动开发(二):创建字符设备驱动

 往期文章:

驱动开发(一):驱动代码的基本框架
驱动开发(二):创建字符设备驱动  ←本文

目录

字符驱动设备的作用

函数

字符驱动设备注册和注销

注册

注销

自动创建设备节点

创建class类型对象

注销class类型对象

提交文件信息

注销文件信息

示例代码

 驱动代码

Makefile

运行结果


字符驱动设备的作用

驱动开发中创建字符设备驱动的目的是为了提供对字符设备的访问接口,使用户空间的应用程序能够通过文件操作系统调用来与字符设备进行交互。

字符设备驱动的作用包括:

  1. 与用户空间的应用程序进行通信:字符设备驱动允许用户空间的应用程序通过文件操作系统调用(如open、read、write、close)来访问设备。应用程序可以通过这些系统调用来读取设备的数据、向设备发送命令或者将数据写入设备。

  2. 实现设备的读写接口:字符设备驱动提供读和写函数,用于从设备中读取数据或向设备中写入数据。这些函数可以根据设备的特性实现相应的读取和写入操作,并把数据传输到用户空间或者从用户空间接收数据。

  3. 处理设备的控制和管理:字符设备驱动可以实现设备的控制和管理功能,包括设备的初始化、中断处理、传输数据的协议等。驱动程序负责确保设备的正确工作,并提供适当的接口供用户空间的应用程序进行操作。

  4. 提供设备的访问权限和保护:字符设备驱动可以限制对设备的访问权限,并提供访问控制和保护机制。驱动程序可以根据需要实现设备的权限控制,确保只有具备相应权限的用户可以访问设备并执行相应操作。

总而言之,字符设备驱动的作用是为用户空间的应用程序提供对设备的访问接口,并实现设备的读写、控制和管理功能,从而实现设备和应用程序之间的数据交互。

函数

字符驱动设备注册和注销

注册

#include <linux/fs.h>  
int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops);
功能:Linux 内核中用于注册字符设备的函数
参数:major:主设备号(一般写0)。当没有指定主设备号时(大于0时),内核会自动分配一个(等于0时)。name:设备名称,通常是一个字符串,用于在 /dev 目录下创建对应的设备文件。fops:一个指向 file_operations 结构体的指针,该结构体定义了一组用于设备操作的函数指针。这些操作包括打开设备、读写设备、释放设备等。
返回值:(大于0时)成功,返回 0。等于0时,返回主设备号如果失败,返回一个负的错误码。
主设备号:大类的驱动需要一个身份(有可能和别的值重复)

次设备号:大类中的小类

注销

void unregister_chrdev(unsigned int major, const char *name)功能:注销一个字符设备驱动参数:@major:主设备号@name:名字返回值:无

自动创建设备节点

自动创建设备节点,即入口(安装驱动的时候)创建设备文件(自动创建的路径是在/dev 下),所以应用层打开文件的时候要注意是/dev/xxx 文件,不要忘了在出口释放资源。

创建class类型对象

#include <linux/device.h>
class_create(owner, name)    功能:创建一个class类型的对象,向用户空间提交目录信息(内核目录的创建)参数:@owner  THIS_MODULE@name   类名字(文件的名字)返回值可以定义一个struct class的指针变量cls接受返回值,然后通过IS_ERR(cls)判断是否失败,如果成功这个宏返回0,失败返回非0值(可以通过PTR_ERR(cls)来获得失败返回的错误码)

注销class类型对象

void class_destroy(struct class *cls)功能:注销一个class类型的对象

提交文件信息

struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)功能:向用户空间提交文件信息参数:@class :录名字@parent:NULL@devt  :设备号    MKDEV(major,0)   @drvdata :NULL@fmt   :文件的名字返回值:成功返回struct device *指针失败返回错误码指针 

struct class *class: 指向设备所属的类的指针。

struct device *parent: 指向父设备的指针。在设备树中,一个设备可以有多个父设备。

dev_t devt: 设备的标识符。它是一个在 /dev 目录下用于访问设备的文件名的一部分。

void *drvdata: 一个指向任意数据的指针,该数据将与新创建的设备关联。这个指针可以用于存储与设备相关的私有数据。

const char *fmt, ...: 一个格式字符串,类似于 printf 函数的第一个参数,用于指定如何格式化后续的参数列表。(就是文件的名字)

注销文件信息

void device_destroy(struct class *class, dev_t devt)功能:注销文件信息

示例代码

 驱动代码

功能仅为创建一个字符设备驱动

#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/fs.h>
#include <linux/device.h>#define MODNAME "lianxi"     //文件的名字
unsigned int major=0;               //主设备号const struct file_operations fops;
struct class *cls;
struct device *dev;//入口  申请资源
static int __init hello_init(void)
{major = register_chrdev(major, MODNAME, &fops);       //注册字符设备if(major<0){printk(KERN_ERR "register chrdev error\n");return major;}cls = class_create(THIS_MODULE, MODNAME);    //创建一个class类型的对象,向用户空间提交目录信息(内核目录的创建)if(IS_ERR(cls)){return PTR_ERR(cls);}dev = device_create(cls, NULL,MKDEV(major,0), NULL,MODNAME );    //向用户空间提交文件信息if(IS_ERR(dev )){return PTR_ERR(dev);}return 0;
}//出口  释放资源
static void __exit hello_exit(void)
{device_destroy(cls, MKDEV(major, 0));         //注销文件信息class_destroy(cls);                                                 //注销一个class类型的对象unregister_chrdev(major, MODNAME);         //注销字符设备驱动
}module_init(hello_init);    //入口
module_exit(hello_exit);    //出口
MODULE_LICENSE("GPL");      //许可证

Makefile

KERNELDIR = /home/linux/kernel/kernel-3.4.39 //=后写你自己的内核顶层的绝对路径
PWD = $(shell pwd)
all:make -C $(KERNELDIR) M=$(PWD) modules.PHONY:clean
clean:make -C $(KERNELDIR) M=$(PWD) cleanobj-m += XXX.o //XXX为你的.c文件名

运行结果

反复安装删除,如果第二次安装报错,说明有资源没释放掉

 

相关文章:

驱动开发(二):创建字符设备驱动

往期文章&#xff1a; 驱动开发&#xff08;一&#xff09;&#xff1a;驱动代码的基本框架 驱动开发&#xff08;二&#xff09;&#xff1a;创建字符设备驱动 ←本文 目录 字符驱动设备的作用 函数 字符驱动设备注册和注销 注册 注销 自动创建设备节点 创建class类…...

Golang:使用时会遇到的错误及解决方法详解

Go语言使用时常常会遇到的一些错误及解决方法&#xff0c;文中的示例代码讲解详细&#xff0c;感兴趣的小伙伴可以了解一下 1、go: go.mod file not found in current directory or any parent directory go mod init name 2、Failed to build the application: main.go:4:2:…...

r语言数据分析案例25-基于向量自回归模型的标准普尔 500 指数长期预测与机制分析

一、背景介绍 2007 年的全球经济危机深刻改变了世界经济格局&#xff0c;引发了一系列连锁反应&#xff0c;波及各大洲。经济增长停滞不前&#xff0c;甚至在某些情况下出现负增长&#xff0c;给出口导向型发展中国家带来了不确定性。实体经济受到的冲击尤为严重&#xff0c;生…...

解决使用Jmeter进行测试时出现“302“,‘‘401“等用户未登录的问题

使用 JMeter 压力测试时解决登录问题的两种方法 在使用 JMeter 进行压力测试时&#xff0c;可能会遇程序存在安全验证&#xff0c;必须登录后才能对里面的具体方法进行测试&#xff1a; 如果遇到登录问题&#xff0c;通常是因为 JMeter 无法模拟用户的登录状态&#xff0c;导…...

MySql通过 Procedure 循环删除数据

一、问题描述 在日常使用运维中&#xff0c;一些特殊情况需要批量删除陈旧或异常数据。 如果通过 delete from 【表名】 where 【条件】 直接删除&#xff0c;可能会由于数据量过大&#xff0c;事务执行时间过长&#xff0c;造成死锁。 二、解决方案 通过 Procedure 使用循环…...

Spring Boot 的启动原理、Spring Boot 自动配置原理

Spring Boot启动原理包含自动装配原理。 Spring Boot 的启动原理&#xff1a; 1. 入口类与 SpringApplication 初始化&#xff1a; 应用程序通常从一个带有 SpringBootApplication 注解的主类开始&#xff0c;这个注解是一个组合注解&#xff0c;包含了 SpringBootConfigurat…...

不会开发的你也能管理好企业漏洞,开源免费工具:洞察(insight II)

公司刚开始建设安全管理时&#xff0c;都是从一片混沌开始的&#xff0c;资源总是不够的&#xff0c;我们每个做安全的人员&#xff0c;又要会渗透&#xff0c;又要抓制度&#xff0c;还得管理各种漏洞。在管理楼栋是&#xff0c;我相信大家都遇到过以下几个问题&#xff1a; …...

java实现两个不同对象的集合复制

场景&#xff1a; 我们开发中会遇到集合对象复制的场景&#xff0c;可以避免代码的重复编写 基于 com.alibaba.fastjson.JSON 实现对象集合的拷贝 对象定义&#xff1a;ObjectA属性&#xff1a;id&#xff0c;name&#xff0c;ageObjectB属性&#xff1a;id&#xff0c;name…...

bind failed: Address already in use

添加代码 这是个很常见的问题&#xff1a;在bind函数之前添加如下代码即可。 int yes 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) -1) { perror("setsockopt"); exit(1); } 查看端口 如果还是不能结果&#xff0c;那么说…...

LabVIEW结构体内部缺陷振动检测

结构体内部缺陷会改变其振动特性&#xff0c;通过振动分析可以检测并定位这些缺陷。本文详细分析内部缺陷对振动的影响&#xff0c;从频谱分析、时域分析和模态分析等多角度探讨基于LabVIEW的检测方法&#xff0c;提供实施步骤和注意事项&#xff0c;帮助工程师有效利用LabVIEW…...

RK3568技术笔记六 新建 Ubuntu Linux 虚拟机

VMware 安装完成后&#xff0c;启动 VMware 软件。启动后在 VMware 主界面点击“创建新的虚拟机”。如下图所示&#xff1a; 开始对新建的虚拟机进行设置。选择“自定义”&#xff0c;然后点击“下一步”。如下图所示&#xff1a; 使用默认配置&#xff0c;单击“下一步”。如下…...

Web前端博客模板下载:一站式解决方案与深度探索

Web前端博客模板下载&#xff1a;一站式解决方案与深度探索 在当今数字化时代&#xff0c;拥有一个美观且功能强大的博客网站已成为许多人的追求。而Web前端博客模板作为构建博客网站的重要工具&#xff0c;其选择和下载对于实现这一目标至关重要。本文将从四个方面、五个方面…...

Docker部署常见应用之大数据实时计算引擎Flink

文章目录 Flink 简介Docker 部署Docker Compose 部署参考文章 Flink 简介 Apache Flink 是一个开源的分布式流批一体化的计算框架&#xff0c;它提供了一个流计算引擎&#xff0c;能够处理有界和无界的数据流。Flink 的核心优势在于其高吞吐量、低延迟的处理能力&#xff0c;以…...

python使用os.getcwd()获取当前路径不正确

# codinggbk import ostry:current_dir os.getcwd()#print(os.path.dirname(os.path.realpath(__file__)))#获取错误print("当前工作目录[不想要]&#xff1a;",current_dir)#获取真实文件夹路径print("当前工作目录[想要]&#xff1a;",os.path.dirname(…...

pycharm终端pip安装模块成功但还是显示找不到 ModuleNotFoundError: No module named

报错信息&#xff1a; ModuleNotFoundError: No module named 但是分明已经安装过此模块&#xff1a; 在cmd运行pip list 查看所有安装过的包找到了安装过&#xff1a; 如果重新安装就是这样&#xff1a;显示已经存在了 问题排查&#xff1a; 直接根据重新安装的显示已存在的…...

iptables教程

1 iptables安装 1.1 iptables和iptables-service的关系 iptables 是基于内核的&#xff0c;和 iptables-services 没有关系&#xff0c;不用安装任何工具包就可以使用 iptable 命令添加的防火墙规则&#xff0c; 但是iptables添加的规则是临时的&#xff0c;基于内存的&…...

破局外贸企业海外通邮难题,U-Mail邮件中继有绝招

在当今全球化的商业环境中&#xff0c;国内企业正扮演着越来越重要的角色&#xff0c;它们不仅在国内市场活跃&#xff0c;而且在全球范围内拓展业务&#xff0c;成为国际贸易中不可或缺的一部分。然而&#xff0c;尽管这些企业在业务扩展上取得了显著成就&#xff0c;但在与海…...

支持向量机(SVM): 从理论到实践的指南(2)

葡萄酒数据集经常被用于机器学习、模式识别和统计分类算法的测试中。由于其特征维度较高&#xff0c;非常适合于验证特征选择和降维方法&#xff0c;例如主成分分析&#xff08;PCA&#xff09;或线性判别分析&#xff08;LDA&#xff09;的效果。同时&#xff0c;由于数据集包…...

PDF格式分析(八十六)——修订注释(Redaction)

修订注释(PDF 1.7及其以上版本),该注释的做用是标识要从文档中删除的内容。 修订注释启用的步骤如下: 1、内容标识。PDF编辑器可指定应删除的文档内容片段或区域,在执行下一个步骤前,用户可以看到、移动和重新定义这些注释。 2、内容移除。PDF阅读器应删除修订注释指…...

【python】flask中Session忽然取不到存储内容怎么办?

尚未确定,后续更新,先别以此为准。 【背景】 用flask写的Web应用,运行不正常,查看原因,发现视图函数a中设定的session内容在视图函数b忽然拿不到了。 【分析】 这个应用在两个服务器间互相Hook,因此可能涉及跨域的问题。 视图函数a设置的session,再次从前端调用视图…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...