Linux 驱动模型

news/2025/3/25 14:25:06/文章来源:https://www.cnblogs.com/tggpx/p/18753768

为了降低设备多样性带来的Linux驱动开发的复杂度,以及设备热拔插处理、电源管理等,Linux内核提出了设备模型(也称作Driver Model)的概念。设备模型将硬件设备归纳、分类,然后抽象出一套标准的数据结构和接口。驱动的开发,就简化为对内核所规定的数据结构的填充和实现。
http://www.wowotech.net/device_model/13.html

bus device driver class

bus: bus的主要功能是管理device和driver之间的关系. 它维护着一个device列表和一个driver列表, 并且负责匹配device和driver.
device: 对硬件设备的抽象, 主要是描述硬件设备的属性.
driver: 对设备驱动的抽象. 负责管理设备.
class: 是一个device的集合,

kobject sysfs

kobject是内核对象的抽象, 它是一个基类, 在c语言中通过结构体内嵌的方式实现, device就是内核对象他们的数据结构会内嵌一个kobject结构体.
kobject主要有以下功能:

  • 通过parent指针,可以将所有Kobject(内核对象)以层次结构的形式组合起来。
  • 用于管理内核对象的生命周期,使用一个引用计数(reference count),来记录Kobject被引用的次数,并在引用次数变为0时把它释放
  • 和sysfs虚拟文件系统配合,将每一个Kobject及其特性,以文件的形式,开放到用户空间.

sysfs是一个虚拟文件系统, 将kobject(内核对象)的属性以文件的形式展现出来, 供用户空间程序读写.

比如一个device, 它挂在某个bus下同时也属于某个class.
首先sys目录下有给device的目录, 里面会有这个device的目录
也可以通过sys/bus/device/XXX 找到
也可以通过sys/class/XXX 找到
如果这个device有*dev(设备号)属性, 会在device目录下有给dev文件, 里面存放设备号(mdev就读取这个文件自动创建设备节点). 并且在/dev/char/下会有一个以设备号命名的链接, 指向这个设备.

bus

bus 的构成

  • name : 总线的名字, 会在sysfs中以目录的形式存在
  • dev_name : 如果bus下的device没有设置init name, 内核会以"bus->dev_name+device ID"的形式,为这样的设备生成一个名称。
  • bus_attrsdev_attrsdrv_attrs : 一些默认的attribute,可以在bus、device或者device_driver添加到内核时,自动为它们添加相应的attribute
  • match : 匹配device和driver的函数.
  • uevent : 当任何属于该Bus的device,发生添加、移除或者其它动作时,Bus模块的核心逻辑就会调用该接口,以便bus driver能够修改环境变量。
  • probe, remove : bus driver的probe和remove函数

sys/bus里能看到已注册的总线. 在bus目录下使用tree可以看到总线的结构.

bus 的操作

通常我们不会新建一个新的总线, 所以这里不介绍如何创建管理总线.

bus_for_each_dev

bus_for_each_drv

BUS_ATTR(name, mode, show, store);

device

device的构成

  • parent : 该设备的父设备,一般是该设备所从属的bus
  • p : 该指针中会保存子设备链表。
  • kobj : 如上文所说,通过嵌入struct kobject实现类似继承的功能(复用kobject相关的代码)。
  • init_name : 该设备的名称,最终是设置到kobj配合sysfs创建目录, 不设置时内核会根据bus->dev_name + device ID生成一个名称。
  • type :
  • bus : 该设备所从属的bus
  • driver : 该设备所使用的driver, 通常在bus match成功后调用driver的probe函数,在验证设备可用后设置该指针。
  • platform_data : 供driver使用, 放一些私有数据
  • power, pm_domain : 电源管理相关
  • devt : 设备号. 一般什么时候被设置?
  • release : 释放设备时调用的函数, 上文提到kobject会自动释放, 就靠这实现.
  • class : 该设备所从属的class
  • groups : 该设备的attribute 集合, sysfs会根据这个集合创建对应的文件.

device的操作

DEVICE_ATTR(name, mode, show, store); //使用这个宏定义一个attribute. mode是文件权限, show和store是读写函数.

device_register(struct device *dev); //注册一个设备

device_unregister(struct device *dev);

device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...) //创建并注册一个设备

通常device也是基类嵌入到一个结构体中的, 比如platform_device. 所以更常用的是其子类的操作函数, 比如platform_device_register.

driver

driver 的构成

  • name : 驱动的名字
  • bus : 该驱动所从属的bus
  • owner, mod_name : 和module相关
  • probe : 当设备匹配成功后调用的函数
  • remove : 当设备被移除时调用的函数
  • shutdown, suspend, resume, pm : 电源管理相关
  • suppress_bind_attrs : 是否启动sysfs的bind/unbind功能. bind/unbind是从用户空间手动的为driver绑定/解绑定指定的设备的机制.
  • groups : 该driver的attribute 集合, sysfs会根据这个集合创建对应的文件.
  • p : 私有数据指针

DRIVER_ATTR(name, mode, show, store); //和DEVICE_ATTR一样, 用于定义一个attribute

在这个架构下, 驱动开发者基本的工作就是实现probe和remove函数.这两个函数的参数都是device, 这样就能获取到device的数据了.
probe 要做以下事情:

  • 验证设备(device)是否可用
  • 字符设备注册, 包括设备号分配, file_operations设置, cdev注册等
    remove 是probe的逆操作, 释放资源.

probe 触发的时机:

  • 将struct device类型的变量注册到内核中时自动触发
  • 将struct device_driver类型的变量注册到内核中时自动触发
  • 手动查找bus下的设备/驱动时手动触发

class

把一些设备归类, 同一类设备就会有相同的属性/操作, 把他们都放到一个class下, 这样就可以把这些共性的东西放到class下, 而不是每个device都有一份.

class 的构成

  • name : class的名字, 会在/sys/class/下以目录的形式存在
  • class_atrrs : 该class的默认attribute, 在/sys/class/xxx_class”下创建对应的attribute文件。
  • dev_attrs : 共性属性, 该class下每个device的attribute, 在/sys/class/xxx_class/xxx_device”下创建对应的attribute文件。
  • dev_uevent : 当该class下有设备发生变化时,会调用class的uevent回调函数。
  • class_release : 用于release自身的回调函数。
  • dev_release : 用于release class内设备的回调函数。在device_release接口中,会依次检查Device、Device Type以及Device所在的class,是否注册release接口,如果有则调用相应的release接口release设备指针。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

原来不是喜欢原子化css,只不过是喜欢tailwind

前言 写css的时候,经常有某个控件只需要些许css样式,但是写行内样式又有优先级问题,从而需要为其单独定义一个class,然而某个控件只是用来布局,没有特定含义,连名称都不好命名。 因此,原子化css应运而生,早期的bootstrap,以及一些组件库中都有使用。 那时叫做工具类,…

c语言分支与循环基础

实验任务一 问题1:生成一个1到100的随机整数 问题2:使输出的整数宽度为4位,不足时在前面补0 问题3:循环生成五个1到100的随机整数,与固定前缀组合后输出类似学员编号的内容实验任务2 问题一:在一次购买流程结束后,清除本次购买的总价,下次运行能重新计算。去掉的话,总…

梯度方差的概念

梯度方差的概念 内容 在深度学习中,梯度方差(Gradient Variance) 是一个关键概念,它直接影响模型的训练稳定性和收敛速度。以下用通俗的语言和实际例子解释它的含义、作用及影响。1. 什么是梯度方差?定义: 梯度方差表示 不同批次数据计算出的梯度之间的波动程度。 如果每…

解决方案 | 如何安全可靠地更改win10的C盘用户名

有的朋友可能最开始由于不知道使用中文名在编程中的各种bug,从而将自己的系统用户名设置成了中文名或者各种奇怪符号的名字,导致在英文编程的时候或者使用英文软件的时候可能出错。为了解决这个问题,网上的文章写得又臭又长,生怕别人看懂学到了技术。本文目的:实现原用户名…

20244106 实验一《Python程序设计》实验报告

20244106 2024-2025-2 《Python程序设计》实验一报告 课程:《Python程序设计》 班级:2441 姓名:孙诗棋 学号:20244106 实验教师:王志强 实验日期:2025年3月20日 必修/选修: 公选课 1.实验内容熟悉Python开发环境; 练习Python运行、调试技能; 编写程序,练习变量和类型…

Nature Communications | 单细胞表观图谱破解颅神经发育疾病非编码变异之谜

摘要总结 这篇文章是2024年9月发表在《Nature Communications》杂志上的一篇研究,标题为“A cell type-aware framework for nominating non-coding variants in Mendelian regulatory disorders”。这篇文章通过整合小鼠胚胎颅运动神经元的单细胞染色质可及性、组蛋白修饰和基…

IOC容器启动及Bean生成流程

目录 一、容器启动IOC启动流程重点二、扫描并注册BeanDefination加载并过滤资源注册BeanDefination三、BeanFactory后置处理 四、注册Bean后置处理器 五、遍历BeanDefination,实例化单例BeanpreInstantiateSingletonsdoGetBean(我们只关注单例)createBean实例化前执行doCrea…

关于QQ提示非官方正版应用

笔者是magisk+lsp+zygisk+shamiko环境,依然是被制裁了,momo检测只有Bootloader未锁定。 也没想在手机上登录QQ(已经摆烂,反正现在工作了,基本都用微信了),只是想在手机打两把王者,登录王者时选择用ipad扫码登录(只是授权登录) 这时候提示我 sign of app is error(100…

苍穹外卖-day04

day-04 25-3-20 新增套餐 需求分析&设计业务规则套餐名称唯一 套餐必须属于某个分类 套餐必须包含菜品 名称、分类、价格、图片为必填项 添加菜品窗口需要根据分类类型来展示菜品 新增的套餐默认为停售状态接口设计(共涉及到4个接口):根据类型查询分类(已完成) 根据分…

提示词工程师自白:我如何用一个技巧解放自己的生产力

“在AI时代的交响乐中,提示词工程师是默默无闻却至关重要的指挥家,用精心编织的语言指引大模型这个智能巨兽创造出人类思维的奇迹。” AI粉嫩特攻队,2025年3月22日。 自从新的生产范式诞生以来,我的工作中多了一项新身份——提示工程师。 在不同的大语言模型之间穿梭,寻求…