linux驱动开发之字符设备与总线设备驱动模型的区别与联系
Linux驱动开发核心概念解析
1. 字符设备(Character Device)
-
定义与特点:
-
以字节流形式进行数据交换,适用于顺序访问的设备(如键盘、鼠标、串口)。
-
用户空间通过设备文件(如
/dev/xxx)访问,依赖主/次设备号标识驱动与实例。
-
-
驱动开发关键步骤:
-
实现文件操作接口:通过
file_operations结构体定义open、read、write、release等函数。 -
注册设备号:
-
动态分配:
alloc_chrdev_region获取主设备号。 -
静态注册:
register_chrdev_region(需确保未被占用)。
-
-
创建设备:
-
初始化
cdev结构体(cdev_init),关联file_operations。 -
添加设备到内核:
cdev_add。
-
-
生成设备节点:
-
自动创建:通过
class_create和device_create,触发udev生成/dev/xxx。 -
手动创建:
mknod命令。
-
-
-
示例代码片段:
c
复制
static struct file_operations fops = {.owner = THIS_MODULE,.open = my_open,.read = my_read,.write = my_write,.release = my_release, };static int __init my_init(void) {alloc_chrdev_region(&dev_num, 0, 1, "mydev");cdev_init(&my_cdev, &fops);cdev_add(&my_cdev, dev_num, 1);my_class = class_create(THIS_MODULE, "myclass");device_create(my_class, NULL, dev_num, NULL, "mydev");return 0; }
2. 总线设备驱动模型(Bus-Device-Driver Model)
-
核心组件:
-
总线(Bus):管理设备与驱动的匹配(如PCI、USB、虚拟总线如
platform)。 -
设备(Device):描述硬件信息(资源、中断等),可通过设备树(Device Tree)动态配置。
-
驱动(Driver):实现设备操作逻辑,包含初始化、资源获取(如
probe)和释放(remove)。
-
-
工作流程:
-
设备注册:向总线注册设备信息(如
platform_device_register)。 -
驱动注册:向总线注册驱动(如
platform_driver_register),提供probe和remove函数。 -
匹配过程:总线根据设备ID表或设备树的
compatible属性匹配设备与驱动。 -
初始化与销毁:匹配成功时调用
probe,失败或卸载时调用remove。
-
-
设备树(Device Tree)的作用:
-
替代硬编码,描述硬件资源(如寄存器地址、中断号)。
-
驱动通过
of_match_table匹配设备树节点,使用of_系列API获取资源(如of_get_property)。
-
-
Platform总线示例:
c
复制
// 设备树节点 mydevice {compatible = "mycompany,mydevice";reg = <0x10000000 0x1000>;interrupts = <0 1>; };// 驱动匹配与初始化 static const struct of_device_id my_of_ids[] = {{ .compatible = "mycompany,mydevice" },{ } };static int my_probe(struct platform_device *pdev) {struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);// 初始化字符设备...return 0; }static struct platform_driver my_driver = {.probe = my_probe,.remove = my_remove,.driver = {.name = "mydrv",.of_match_table = my_of_ids,}, }; module_platform_driver(my_driver);
3. 字符设备与总线模型的整合
-
场景:基于总线(如I2C)的字符设备(如传感器)。
-
总线驱动:处理总线协议(如I2C读写),在
probe中注册字符设备。 -
字符设备驱动:通过
file_operations暴露用户接口,调用总线驱动提供的底层操作。
-
-
优势:
-
解耦硬件与接口:总线驱动处理硬件细节,字符设备驱动处理用户交互。
-
复用性:同一总线驱动支持多种设备,同一字符设备驱动适配不同总线。
-
4. 关键工具与调试
-
sysfs:在
/sys/bus、/sys/devices查看设备层次结构。 -
调试技术:
printk、dmesg、devtmpfs自动创建设备节点。 -
动态加载:
insmod/rmmod加载驱动模块。
总结
-
字符设备:关注用户空间接口,实现字节流操作。
-
总线模型:分离设备与驱动,提升灵活性和可维护性。
-
设备树:动态配置硬件资源,增强代码可移植性。
学习建议:通过实际项目(如LED控制、传感器驱动)结合代码实践,深入理解设备树配置、总线匹配机制及字符设备接口的实现。
首先,字符设备,我记得它们是用来处理按字节流进行数据交换的设备,比如键盘、鼠标、串口这些。和块设备不同,块设备是按块来操作的,比如硬盘。字符设备驱动需要实现哪些东西呢?应该是要实现file_operations结构体里的那些函数,比如open、read、write、release之类的。用户空间通过设备文件来访问这些设备,比如/dev下面的那些节点,主设备号用来标识驱动,次设备号区分不同实例。那创建字符设备的时候,是不是要用register_chrdev或者更新的方法,比如alloc_chrdev_region加上cdev_init和cdev_add?可能还有设备类相关的操作,比如class_create和device_create,这样udev会自动创建设备节点。
然后是总线设备驱动模型,这部分我有点模糊。总线模型应该是指设备如何连接到总线,比如PCI、USB、I2C这些总线类型。总线设备驱动模型分为总线、设备、驱动三个部分,对吧?总线负责匹配设备和驱动,当设备插入时,总线会寻找对应的驱动,或者驱动加载时寻找对应的设备。这样的话,设备和驱动是分开注册的,通过总线进行匹配。设备结构体platform_device,驱动结构体platform_driver,可能属于平台设备,不依赖于物理总线的那种虚拟总线?比如SOC上的各种控制器。那platform_driver里面应该有probe和remove函数,当设备匹配时,probe会被调用,进行初始化,remove则是清理资源。匹配的依据是什么呢?可能是通过名字,或者是设备树中的兼容性字符串。
设备树在总线模型中起什么作用呢?设备树用来描述硬件配置,代替原来的硬编码。驱动可以通过设备树获取资源,比如内存地址、中断号,而不需要在内核中写死。这样同一个驱动可以支持不同的硬件配置,只要设备树描述正确。比如,platform设备可能从设备树中获取资源,驱动使用of_match_table来匹配设备树中的节点。
那总线模型中的匹配过程是怎样的呢?当设备注册时,总线会检查是否有对应的驱动已经注册,如果有的话,调用驱动的probe函数。同样,当驱动注册时,总线会检查是否有对应的设备存在,有的话也会调用probe。匹配通常基于设备ID表或者设备树中的compatible属性。对于platform设备,可能用platform_device_id或者设备树中的compatible字符串来匹配。
字符设备和总线模型之间的关系是什么呢?比如,一个字符设备驱动可能基于某个总线模型。例如,一个I2C设备驱动,属于总线模型中的驱动部分,同时它提供的设备可能作为字符设备被用户空间访问。这时候,驱动需要同时处理总线的匹配和字符设备的操作函数。
可能还有一些例子,比如编写一个简单的字符设备驱动,需要注册字符设备,实现file_operations。而如果是总线模型的设备,比如platform驱动,则需要注册platform_driver,并在probe函数中注册字符设备,这样当platform设备匹配时,probe被调用,进而创建设备节点。
还有,sysfs的作用是什么?总线、设备、驱动都会在sysfs中有对应的条目,用户空间可以通过sysfs查看设备和驱动的信息,进行一些配置或者状态查询。例如,/sys/bus/下面有各种总线的目录,里面包含了注册的设备和驱动。
我是不是漏掉了什么重要的概念?比如,设备模型中的kobject、kset、ktype这些底层结构?可能总线模型是基于kobject的sysfs表示的,每个设备、驱动都是kobject的子对象,通过层次结构组织起来。这样sysfs就能展示出设备树的层次结构。
另外,模块的加载和卸载过程,字符设备驱动模块在加载时需要注册设备,卸载时注销。而对于总线模型中的驱动模块,加载时会注册驱动,卸载时注销驱动,并调用remove函数释放资源。
还有设备号的申请,动态分配还是静态注册?现在更推荐动态分配,使用alloc_chrdev_region,这样可以避免冲突。静态的话需要知道哪些主设备号未被占用,可能不太方便。
总结一下,字符设备驱动关注的是用户空间的接口,通过file_operations提供操作函数。而总线设备驱动模型关注的是设备与驱动的匹配和管理,利用总线作为中介,分离设备和驱动的代码,提高可重用性和可维护性。设备树在此模型中用于硬件描述,使得驱动代码更独立于具体硬件配置。
现在可能存在的疑问点:总线模型中platform总线和实际物理总线(如I2C)的区别;设备树如何具体在驱动中被解析和使用;probe函数的具体作用和调用时机;sysfs与设备模型的关系;以及如何将字符设备驱动整合到总线模型中。需要进一步查阅资料或例子来验证这些理解是否正确。
相关文章:
linux驱动开发之字符设备与总线设备驱动模型的区别与联系
Linux驱动开发核心概念解析 1. 字符设备(Character Device) 定义与特点: 以字节流形式进行数据交换,适用于顺序访问的设备(如键盘、鼠标、串口)。 用户空间通过设备文件(如/dev/xxx࿰…...
AI deepseek对数据治理的影响
DEEPSEEK作为智能一款助手,在数据治理体系中具有深远的影响。它通过提供智能化、自动化和高效化的解决方案,推动企业在数据治理变革与领域的优化。以下是EPSEEK对数据治理体系影响的多角度分析: 一、战略层面:推动数据治理目标的…...
DeepSeek各版本说明与优缺点分析
DeepSeek各版本说明与优缺点分析 DeepSeek是最近人工智能领域备受瞩目的一个语言模型系列,其在不同版本的发布过程中,逐步加强了对多种任务的处理能力。本文将详细介绍DeepSeek的各版本,从版本的发布时间、特点、优势以及不足之处࿰…...
iOS 老项目适配 #Preview 预览功能
前言 iOS 开发者 最憋屈的就是UI 布局慢,一直以来没有实时预览功能,虽然swiftUI 早就支持了,但是目前主流还是使用UIKit在布局,iOS 17 苹果推出了 #Preview 可以支持UIKit 实时预览,但是仅仅是 iOS 17,老项目怎么办呢?于是就有了这篇 老项目适配 #Preview 预览 的文章,…...
在ubuntu22.04上先部署docker,再编译安装kamailio,附详细操作流程及docker和makailio的版本号
以下是在Ubuntu 22.04上部署Docker并编译安装Kamailio的详细操作流程,包含版本号信息: 一、部署Docker(版本:24.0.7) 更新系统包 sudo apt update && sudo apt upgrade -y安装依赖工具 sudo apt install -y ap…...
蓝桥杯试题:排序
一、问题描述 给定 nn 个正整数 a1,a2,…,ana1,a2,…,an,你可以将它们任意排序。现要将这 nn 个数字连接成一排,即令相邻数字收尾相接,组成一个数。问,这个数最大可以是多少。 输入格式 第一行输入一个正整数 nnÿ…...
C++常用拷贝和替换算法
算法简介: copy // 容器内指定的元素拷贝到另一容器replace // 将容器内指定范围的旧元素改为新元素replace_if // 容器内指定范围满足条件的元素替换为新元素swap //互换两个容器的元素 1. copy 功能描述: 将容器内指定范围的数据拷贝到另一容器中函…...
2024年12月 Scratch 图形化(三级)真题解析 中国电子学会全国青少年软件编程等级考试
202412 Scratch 图形化(三级)真题解析 中国电子学会全国青少年软件编程等级考试 一、选择题(共18题,共50分) 第 1 题 气温和对应的穿衣建议如下表所示,下列选项能正确给出穿衣建议的是?( ) A. …...
C# 中记录(Record)详解
从C#9.0开始,我们有了一个有趣的语法糖:记录(record) 为什么提供记录? 开发过程中,我们往往会创建一些简单的实体,它们仅仅拥有一些简单的属性,可能还有几个简单的方法,比如DTO等等…...
【MQTT协议 03】 抓包分析
一、MQTT测试工具 1、mqtt服务器 emqx 2、mqtt 客户端 mqttx 3、抓包工具 wireshark 搭建参考 【MQTT 协议 01】MQTT 服务器搭建_mqtt服务器搭建-CSDN博客 二、报文测试 2.1、CONNECT (客户端连接) 2.1.1、抓包 2.1.2、解析 #16进制表示 10300…...
深度学习-100-RAG技术之最简单的RAG系统概念和效果优化提升方向
文章目录 1 数据是基础2 Naive RAG(最简单的RAG系统)2.1 RAG周边技术2.2 标准的RAG流程2.3 RAG的潜在问题2.4 如何应对RAG的问题3 优化方向3.1 原始数据创建/准备3.1.1 易于理解的文本3.1.2 提高数据质量3.2 预检索优化3.2.1 分块优化3.2.2 添加元数据3.2.3 选对嵌入模型3.2.4 …...
Redis面试题总结(题目来源JavaGuide)
Redis 基础 问题1:Redis 有什么作用?为什么要用 Redis/为什么要用缓存? Redis 是一个开源的高性能键值对数据库,它的作用主要体现在以下几个方面: 缓存:Redis 常被用作缓存系统,可以将频繁访问的数据存储…...
Django 多数据库
django 支持项目连接多个数据库 DATABASES = {default: {ENGINE: django.db.backends.mysql,NAME: xxx,USER: root,"PASSWORD": xxxxx,HOST: xxxx,PORT: 3306,},bak: {ENGINE: django.db.backends.mysql,NAME: xxx,USER: root,"PASSWORD": xxxx,HOST: xxx…...
为AI聊天工具添加一个知识系统 之87 详细设计之28 Derivation 统一建模元模型 之1
文本要点 要点 Derivation 统一建模元模型 Derivation 统一建模元模型:意识原型的祖传代码,即支撑 程序框架的 符号学中的 自然和逻辑树。 这棵树的雏形中描述了三种建模工件:语用钩子,语法糖和语义胶水。 三种工件对应的三“…...
手机上运行AI大模型(Deepseek等)
最近deepseek的大火,让大家掀起新一波的本地部署运行大模型的热潮,特别是deepseek有蒸馏的小参数量版本,电脑上就相当方便了,直接ollamaopen-webui这种类似的组合就可以轻松地实现,只要硬件,如显存…...
电商项目-分布式事务(四)基于消息队列实现分布式事务
基于消息队列实现分布式事务,实现消息最终一致性 如何基于消息队列实现分布式事务? 通过消息队列实现分布式事务的话,可以保证当前数据的最终一致性。实现思路:将大的分布式事务,进行拆分,拆分成若干个小…...
leetcode_双指针 160.相交链表
160.相交链表 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 思路: 本题中,交点不是数值相等,而是指针相等 双指针遍历两遍后必定相遇,…...
深入理解浮点数:单精度、双精度、半精度和BFloat16详解
文章目录 深入理解浮点数:单精度、双精度、半精度和BFloat16详解 🔢简介 🌟1. 单精度(Single Precision)🎯应用场景 🚀 2. 双精度(Double Precision)💪应用场…...
Verilog基础(三):过程
过程(Procedures) - Always块 – 组合逻辑 (Always blocks – Combinational) 由于数字电路是由电线相连的逻辑门组成的,所以任何电路都可以表示为模块和赋值语句的某种组合. 然而,有时这不是描述电路最方便的方法. 两种always block是十分有用的: 组合逻辑: always @(…...
前端知识速记:POST和GET
前端知识速记:POST和GET请求的区别 一、GET请求概述 GET请求是一种用于获取服务器资源的请求方式。**使用GET请求时,数据通过URL传递,适合用于获取数据而不修改资源。**以下是GET请求的一些基本特征: 数据附在URL后面ÿ…...
【Java】MyBatis动态SQL
在MyBatis中使用动态SQL语句。 动态SQL是指根据参数数据动态组织SQL的技术。 生活中的案例: 在京东上买东西时,用户搜索商品,可以选择筛选条件,比如品牌,价格,材质等,也可以不使用筛选条件。这时…...
java进阶知识点
java回收机制 浅谈java中的反射 依赖注入的简单理解 通过接口的引用和构造方法的表达,将一些事情整好了反过来传给需要用到的地方~ 这样做得好处:做到了单一职责,并且提高了复用性,解耦了之后,任你如何实现…...
Java/Kotlin HashMap 等集合引发 ConcurrentModificationException
在对一些非并发集合同时进行读写的时候,会抛出 ConcurrentModificationException 异常产生示例 示例一(单线程): 遍历集合时候去修改 抛出 ConcurrentModificationException 的主要原因是当你在遍历一个集合(如 Map…...
拍照对比,X70 PRO与X90 PRO+的细节差异
以下是局部截图(上X70P下X90PP) 对比1 这里看不出差异。 对比2 X90PP的字明显更清楚。 对比3 中下的字,X90PP显然更清楚。...
Node.js与嵌入式开发:打破界限的创新结合
文章目录 一、Node.js的本质与核心优势1.1 什么是Node.js?1.2 嵌入式开发的范式转变二、Node.js与嵌入式结合的四大技术路径2.1 硬件交互层2.2 物联网协议栈2.3 边缘计算架构2.4 轻量化运行时方案三、实战案例:智能农业监测系统3.1 硬件配置3.2 软件架构3.3 核心代码片段四、…...
使用java调用deepseek,调用大模型,处理问题。ollama
废话不多,直接上代码 Testpublic void test7171111231233(){// url:放请求地址String url "http://localhost:11434/api/generate";HttpRequest request HttpUtil.createPost(url);Map<String, String> headers new HashMap<>();String a…...
Linux驱动---字符设备
目录 一、基础简介 1.1、Linux设备驱动分类 1.2、字符设备驱动概念 二、驱动基本构成 2.1、驱动模块的加载和卸载 2.2、添加LICENNSE以及其他信息 三、字符设备驱动开发步骤 3.1、分配主次设备号 3.1.1 主次设备号 3.1.2静态注册设备号 3.1.3动态注册设备号 3.1.4释…...
php7.3安装php7.3-gmp扩展踩坑总结
环境: 容器里面为php7.3.3版本 服务器也为php7.3.3-14版本,但是因为业务量太大需要在服务器里面跑脚本 容器里面为 alpine 系统,安装各种扩展 服务器里面开发服为 ubuntu 16.04.7 LTS (Xenial Xerus) 系统 服务器线上为 ubuntu 20.04.6 LTS (…...
javaEE-8.JVM(八股文系列)
目录 一.简介 二.JVM中的内存划分 JVM的内存划分图: 堆区:编辑 栈区:编辑 程序计数器:编辑 元数据区:编辑 经典笔试题: 三,JVM的类加载机制 1.加载: 2.验证: 3.准备: 4.解析: 5.初始化: 双亲委派模型 概念: JVM的类加…...
大语言模型轻量化:知识蒸馏的范式迁移与工程实践
大语言模型轻量化:知识蒸馏的范式迁移与工程实践 🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 摘要 在大型语言模型ÿ…...
