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

linux字符设备驱动程序

字符设备驱动程序简介

 linux系统中万物皆文件,驱动程序加载后会在/dev目录下生成一
个对应的文件,如/dev/led。应用程序就是先用open打开该文件,
用write控制led的亮灭,用read读取led的亮灭,用完之后用close
关闭该文件。
这里需要注意的是,应用程序运行在用户空间,驱动程序运行
在内核空间。应用程序必须使用一个叫做“系统调用”的方法
来实现从用户空间“陷入”到内核空间,这样才能实现对底层
驱动的操作。一个open函数执行的过程如下
在这里插入图片描述

字符设备驱动编写

linux源码中字符设备驱动程序存放在driver/char目录下,我们也可以将我们自己的驱动程序保存在该目录下
在driver/char下创建源文件first_driver.c并在文件中填入如下代码

模块加载使用 __init 函数
模块卸载使用 __exit函数
请添加图片描述

字符设备驱动注册函数int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)

1. unsigned int major:主设备号,这里就不得不提一下linux中的
设备号了。一个字符设备或者块设备都有一个主设备号和次
设备号。主设备号和次设备号统称为设备号。主设备号用来
表示一个特定的驱动程序。次设备号用来表示使用该驱动程
序的设备。简单来说,linux需要一个数来管理某个驱动程序
和使用这个驱动程序的设备。很明显,这个设备号具有唯一
性。我们可以使用cat /proc/devices命令即可查看当前系统中
所有已经使用了的设备号。在接下来的程序中,我们可以设
置一个静态的主设备号,比如200。设置时一定要注意不能使
用已经用了的主设备号。
2. const char *name:为你的驱动程序起一个名字
3. struct file_operations *fops:这是一个指向file_operations结构
体变量的指针,这个结构体里面的成员绝大多数都是函数的
指针。这些函数的指针指向一个我们编写的函数,每个函数
都有着各自的作用。

file_operations fops

该函数成员有以下一些:
请添加图片描述
其中我们驱动编写需要用到的参数有:

①open 函数用于打开设备文件
② release 函数用于释放(关闭)设备文件,与应用程序中的close 
函数对应
③ read 函数用于读取设备文件
④write 函数用于向设备文件写入(发送)数据
⑤ owner 拥有该结构体的模块的指针,一般设置为
THIS_MODUL

为了调用注册字符设备驱动函数,不得不先准备一个file_operations结构体变量,而这个结
构体变量中必要的成员,必须提前准备几个函数
请添加图片描述

在init__中调用注册函数请添加图片描述

编译字符设备驱动程序

这种方法需要我们的驱动源码就放在driver/char目录中,恰好我
们就是这么做的。步骤如下:

1.打开drivers/char/Kconfig 文件并添加如下内容

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
在这里就可以找到自己刚才添加的设备了
请添加图片描述

2.打开drivers/char/Makefile并添加下面内容

![请添加图片描述](https://i-blog.csdnimg.cn/direct/请添加图片描述

编写驱动程序的调用

正如之前所提到的,驱动程序的调用是通过应用程序的文件IO
实现的。所以调用驱动程序就是编写一个简单的文件IO程序。

这里open
这里open中打开的就是/dev/+你的设备名称(在驱动自己设置的,如上面代码中我写的“led”)。

到这里基本驱动就已经完成了,但是我们并没有真正控制一个led的亮灭,这就需要我们对硬件对应的寄存器进行操作

LED标准驱动程序(s3c2440)

在编写驱动之前,我们必须知道寄存器的地址是什么,但是我们并不能通过寄存器的物理地址去直接访问它,在此不得不使用MMU这个工具(内存管理单元)。

1.完成虚拟空间到物理空间的映射
2.内存保护,设置存储器的访问权限,设置虚拟存储空间的缓冲特性

我们重点来看一下第①点,也就是虚拟空间到物理空间的映射,也叫做
地址映射。首先了解两个地址概念:虚拟地址(VA,Virtual Address)、物
理地址(PA,Physcical Address)。对于32 位的处理器来说,虚拟地址范
围是2^32=4GB,我们的开发板上有64MB 的SDRAM,这64MB 的内存
就是物理内存,经过MMU 可以将其映射到整个4GB 的虚拟空间
那么换句话说就是由于linux启动时启用了MMU,所以在编写程序时用
到的都是虚拟内存,而不是物理内存。但是操作led必须使用物理内存
Led驱动程序请添加图片描述

可以在keil4/5中查看对应寄存器的物理地址,在此我们需要用到的寄存器有GPBCON(0x56000010)和GPBDAT(0x56000014),但是我们在机器中直接访问,系统会认为我们输入的是虚拟地址,而无法控制我们想要控制的寄存器,所以我们必须完成一次虚拟映射以获取它们的虚拟地址

#define ioremap(cookie,size) ……

在cookie中输入寄存器的物理地址
在size中输入地址字节数大小
第53-55行为GPIO设置,和裸机设置一样
请添加图片描述

地址常量和寄存器变量定义如下请添加图片描述

可以看出REG_GPBCON和REG_GPBDAT就是两个普通的指针,设置寄
存器需要使用指针的间接访问
在驱动程序被卸载的时候也需要取消映射

请添加图片描述
led驱动程序不要应用程序“读取”,只需要编写写入函数就行
请添加图片描述
之前的代码中在注册字符设备驱动的时候我们使用了一个静态的主设备
号200,很明显,200这个主设备号如何已经被使用了,那么我们就无法
完成注册。最好的办法就是由系统给我们提供一个合法的设备号

申请设备号的函数int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)

参数dev的数据类型是dev_t,这个数据类型就是linux设备号的数据类型,
需要注意的是,这个数据类型的本身就是unsigned int型,其中包括了
主设备号和次设备号。主设备号占高12位,次设备号占20位。l很明显,
主设备号从0~4095,次设备号虽然占20位,但是它的有效范围是从
0~256。l系统提供了两个宏,分别用于从一个设备号中提取主设备号和
次设备号:MAJOR和MINOR。这个参数就是需要我们定义一个dev_t变
量,函数将获得的设备号通过这个参数传递出来。

dev:传递一个dev_t类型的变量地址
baseminor:此设备号的起始值(次设备号)count:申请几个此设备
name:设备名
返回0表示成功,负数表示不成功

在led驱动中添加全局变量static dev_t dev_num,并调用
alloc_chrdev_region函数申请合法的设备号

设备号与驱动程序关联 int cdev_add(struct cdev *p, dev_t dev, unsigned count);

1.该函数需要一个cdev结构体变量的地址,struct cdev结构体中包含了
dev_t和struct operations,所以它能够把dev_t和驱动程序联系在一
起
2. dev参数就是之前申请到的设备号
3.申请的次设备号的个数

在调用cdev_add函数之前,还需要把我们定义的cdev变量初始化一下,
这里调用

void cdev_init(struct cdev *cdev, const struct file_operations *fops);

  1. cdev变量的地址
    2.文件操作结构体变量地址

操作如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

自动添加节点

创建class使用带参宏#define class_create(owner, name)

其实这个宏又调用了__class_create(owner, name, &__key)函数

1. owenr指向模块的指针,这里只需传THIS_MODULE
2. name为该设备的类型起个名字
3.该函数返回struct class *,用宏IS_ERR判断是否合法

创建device使用函数

struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, …);

  1. class参数:之前获得的指针
  2. parent:设备的父设备指针,传NULL
  3. devt:设备号
  4. drvdata:驱动需要的额外参数,这里传NULL
  5. fmt:将来在/det目录下生成的文件名

请添加图片描述
模块卸载
请添加图片描述

相关文章:

linux字符设备驱动程序

字符设备驱动程序简介  linux系统中万物皆文件,驱动程序加载后会在/dev目录下生成一 个对应的文件,如/dev/led。应用程序就是先用open打开该文件, 用write控制led的亮灭,用read读取led的亮灭,用完之后用close 关闭该…...

【pyhton】python如何实现将word等文档中的文字转换成语音

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

Claude Enterprise推出计划

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

【前端】CSS控制style样式失效

在CSS中,可以通过几种方式控制或禁用特定的style样式。 使用all: unset来重置所有可继承的属性,并清除所有的样式: .element {all: unset;} 使用inherit值来使属性获取其父元素的值: .element {color: inherit;font-size: inh…...

How can I load the openai api configuration through js in html?

题意:怎样在HTML中通过JavaScript加载OpenAI API配置 问题背景: I am trying to send a request through js in my html so that openai analyzes it and sends a response, but if in the js I put the following: 我正在尝试通过HTML中的JavaScript发…...

Pipeline流水线通过git拉取Jenkinsfile报错 error: RPC failed; result=22, HTTP code = 404

Pipeline流水线通过git拉取Jenkinsfile报错 error: RPC failed; result22, HTTP code 404 在学习共享库时使用通过git拉取jenkinsfile时,报错在排查gitlab服务状态,网络通讯,防火墙规则以及Jenkins凭据均可以正常使用,最后发现的…...

【与C++的邂逅】--- string容器使用

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: 与C的邂逅 本篇博客我们将来了解string容器本身以及接口的使用。 string是串,本质是一个字符数组,可以对其进行增删查改。 &am…...

1-18 平滑处理——高斯滤波 opencv树莓派4B 入门系列笔记

目录 一、提前准备 二、代码详解 cv2.GaussianBlur函数用于对图像进行高斯滤波。高斯滤波是一种平滑图像的技术,用于减少噪声和细节。函数的三个参数如下: 三、运行结果 四、完整工程贴出 一、提前准备 1、树莓派4B 及 64位系统 2、提前安装opencv库…...

小爱打工,你躺平!让「微信AI小助理」接管你的文件处理,一个字:爽!

前两天,搞了个微信 AI 小助理-小爱(AI),爸妈玩的不亦乐乎。 零风险!零费用!我把AI接入微信群,爸妈玩嗨了,附教程(下) 最近一直在迭代中,挖掘小爱的无限潜力: 链接丢给…...

管理学习(一)马云《赢在中国》创业演讲整理

目录 一、小公司也需要制度二、不要害怕冒险三、创业者要的不是技术,而是胆识四、不要惧怕和大企业竞争五、理念不一样,老板永远是对的六、要真实地为客户创造价值七、跟风险投资谈判,说到要做到八、风险投资,只能帮你不能救你九、…...

Opencv中的直方图(2)计算图像的直方图函数calcHist()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 计算一组数组的直方图。 函数 cv::calcHist 计算一个或多个数组的直方图。用于递增直方图bin的元组的元素是从相同位置的相应输入数组中获取的。…...

Buzzer:一款针对eBPF的安全检测与模糊测试工具

关于Buzzer Buzzer是一款功能强大的模糊测试工具链,该工具基于Go语言开发,可以帮助广大研究人员简单高效地开发针对eBPF的模糊测试策略。 功能介绍 下面给出的是当前版本的Buzzer整体架构: 元素解析: 1、ControlUnit&#xff1a…...

若依框架登录鉴权详解(动态路由)

若依框架登录鉴权:1.获取token(过期在响应拦截器中实现),2.基于RBAC模型获取用户、角色和权限信息(在路由前置守卫),3.根据用户权限动态生成(从字符串->组件,根据permission添加动…...

孤儿进程、僵尸进程、守护进程(精灵进程)

目录 一、孤儿进程 二、僵尸进程 三、守护进程&#xff08;精灵进程&#xff09; 一、孤儿进程 定义&#xff1a;孤儿进程是指那些其父进程已经结束&#xff0c;但它们依然在运行的进程 创建一个孤儿进程&#xff1a; #include <stdio.h> #include <stdlib.h> #in…...

Centos9 网卡配置文件

1、Centos stream 9 网络介结 Centos以前版本&#xff0c;NetworkManage以ifcfg格式存储网络配置文件在/etc/sysconfig/networkscripts/目录中。但是&#xff0c;Centos steam 9现已弃用ifcfg格式&#xff0c;默认情况下&#xff0c;NetworkManage不再创建此格式的新配置文件。…...

ios免签H5

1、windows下载mobileconfig文件制作工具&#xff0c;可在csdn搜索iPhone_Mobileconfig_Tool下载安装&#xff1b;IOS 从APP Store 下载Apple Configurator 2 2、用申请的域名SSL证书给mobieconfig文件签名&#xff0c;最好下载Apache证书&#xff0c;里面包含 AE86211.crt…...

RedHat9.x-基本操作

本例以RedHat9.3为例 安装ifconfig命令 # dnf -y install net-tools 安装图形化 # dnf -y groupinstall "Server with GUI" 安装tmux # dnf -y install tmux -- screen已弃用 network-scripts 已弃用...

华为 HCIP-Datacom H12-821 题库 (5)

有需要题库的可以看主页置顶 需要题库的加Q裙 V群仅进行学习交流 1.以下关于堆叠 MAD 检测说法错误的是&#xff1f; A、堆系统互为代理进行 MAD 检测时&#xff0c;两个堆系统可以使用相同的D omain ID B、MAD 检测的方式分为直连检测、代理检测 C、MAD 代理检测要求所有堆叠…...

vue中oninput和@input区别

使用oninput绑定&#xff0c;此方法会导致中文输入法情况下&#xff0c;v-model和value不一致&#xff0c;原因是在中文输入法情况下vue中的v-model会自动return&#xff0c;v-mode绑定的值不变&#xff0c;value绑定的值可变。 :οninput"valuevalue.replace(/\D/g,)&qu…...

分布式锁(Redis的setnx、Redisson)

一、使用Redis的setnx实现分布式锁 1、使用Redis的setnx实现分布式锁出现的问题 &#xff08;1&#xff09; 宕机时的锁释放问题 在分布式系统中&#xff0c;如果一个节点获取了锁&#xff0c;但在执行任务过程中发生故障&#xff0c;没有释放锁&#xff0c;其他节点可能会一…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

用递归算法解锁「子集」问题 —— LeetCode 78题解析

文章目录 一、题目介绍二、递归思路详解&#xff1a;从决策树开始理解三、解法一&#xff1a;二叉决策树 DFS四、解法二&#xff1a;组合式回溯写法&#xff08;推荐&#xff09;五、解法对比 递归算法是编程中一种非常强大且常见的思想&#xff0c;它能够优雅地解决很多复杂的…...