调用 device_add():将设备添加到内核的设备层次结构中。 与总线关联,触发设备与驱动的匹配流程。

linux内核部件分析(九)——设备驱动模型之device-driver 前面我们分析了device、driver、bus三种类型,主要是三者的注册与注销,在sysfs中的目录与属性文件创建等内容。本节就来详细分析下,在设备注册到总线上时,总线是如何为其寻找对应的驱动的;在驱动注册到总线上时,总线又是如何为其寻找对应的设备的。     本节的实现代码 阅读详情

device_add() 是 Linux 内核设备模型中的核心函数,用于将设备添加到内核的设备层次结构中,并与总线关联,触发设备与驱动的匹配流程。它的功能可以分为以下几个关键步骤:


1. 函数原型


C

int device_add(struct device *dev)

  • dev:指向设备结构体的指针,描述设备的各种信息(如总线类型、设备名称、父设备等)。

2. device_add() 的主要功能

device_add() 的主要职责是:

  1. 将设备注册到内核的设备模型中,建立设备的层次结构(如父子关系)。
  2. 将设备与所属总线关联,触发设备与驱动的匹配流程。
  3. 为设备创建相关的用户空间接口(如 sysfs 文件)。
  4. 通知用户空间(如 udev)有新设备被添加。

3. 函数实现详细解析

以下是 device_add() 的核心代码逻辑逐步解析:

a. 检查设备的必要字段

C

if (!dev->p || !dev->bus) return -EINVAL;

  • 检查设备结构体中是否初始化了必要字段:
    • dev->p:设备的私有数据(struct device_private)。
    • dev->bus:设备所属的总线类型(如 platform_bus_type)。
  • 如果这些字段未初始化,则返回错误。

b. 设置设备的层次关系

C

dev->parent = get_device(dev->parent); kobject_set_name(&dev->kobj, dev_name(dev));

  • 设置父设备:

    • 如果该设备有父设备(dev->parent),通过 get_device() 设置父设备,确保父子关系正确。
    • 父设备通常是一个表示设备容器的设备(如 PCI 总线设备、platform 总线设备等)。
  • 设置设备的 kobject 名字:

    • kobject_set_name() 给设备的内核对象(kobject)设置一个唯一名字,通常是设备的名字(dev_name(dev))。

c. 添加设备到内核设备模型

C

ret = kobject_add(&dev->kobj, dev->parent ? &dev->parent->kobj : NULL, dev_name(dev)); if (ret < 0) goto Error;

  • kobject_add():

    • 将设备的 kobject 添加到内核的设备层次结构中。
    • 如果设备有父设备,则将其添加到父设备的 kobject 子结构中。
    • kobject 是内核对象的基础结构,用于管理设备的生命周期和 sysfs 挂载点。
  • 错误处理:

    • 如果 kobject_add() 失败,则释放资源并返回错误。

d. 与总线关联

C

ret = bus_add_device(dev); if (ret) goto Error;

  • bus_add_device():
    • 将设备添加到设备所属总线(dev->bus)中。
    • 这一步是设备与总线关联的关键,触发设备与驱动的匹配流程。

e. 自动匹配设备与驱动

bus_add_device() 内部会调用 device_attach(),触发设备与驱动的匹配流程:


C

int bus_add_device(struct device *dev) { struct bus_type *bus = dev->bus; int error = 0; // 自动驱动匹配 if (bus->p->drivers_autoprobe) { error = device_attach(dev); // 关键步骤 } return error; }

device_attach()
  • device_attach() 是设备模型中用于尝试匹配设备和驱动的函数。
  • 它会遍历总线上的所有驱动,调用驱动的 match() 函数检查是否与设备匹配。

关键代码:


C

int device_attach(struct device *dev) { return __device_attach(dev, false); } static int __device_attach(struct device *dev, bool allow_async) { struct bus_type *bus = dev->bus; struct device_driver *drv; // 遍历总线上的所有驱动 if (bus && bus->match) { list_for_each_entry(drv, &bus->p->drivers_list, p->drivers_list) { if (bus->match(dev, drv)) { // 匹配设备与驱动 ret = driver_probe_device(drv, dev); // 绑定驱动到设备 break; } } } return ret; }

驱动匹配逻辑
  • 总线提供 match() 函数,用来匹配设备与驱动。
  • 对于 platform_bus,匹配逻辑通常是设备名字和驱动名字是否相同。

匹配函数:


C

int platform_match(struct device *dev, struct device_driver *drv) { struct platform_device *pdev = to_platform_device(dev); struct platform_driver *pdrv = to_platform_driver(drv); // 匹配设备名字和驱动名字 return strcmp(pdev->name, pdrv->driver.name) == 0; }

如果匹配成功,就会调用 driver_probe_device(),将驱动绑定到设备。


f. 创建用户空间接口

C

ret = device_add_groups(dev, dev->groups); if (ret) goto Error;

  • device_add_groups():
    • 为设备创建相关的属性组(sysfs 文件)。
    • 用户空间可以通过 sysfs 访问设备的属性。

g. 通知用户空间

C

kobject_uevent(&dev->kobj, KOBJ_ADD);

  • kobject_uevent():
    • 向用户空间发送 KOBJ_ADD 事件,通知设备被添加。
    • 用户空间工具(如 udev)可以捕获这个事件,进行设备的管理和初始化。

4. 总结流程

device_add() 的完整流程如下:

  1. 检查设备结构体是否有效。
  2. 设置设备的层次关系(父设备、名字等)。
  3. 将设备的 kobject 添加到内核设备模型。
  4. 与总线关联,调用 bus_add_device()。
  5. 自动匹配设备与驱动,调用 device_attach()。
  6. 为设备创建用户空间属性接口(sysfs 文件)。
  7. 发送 KOBJ_ADD 事件,通知用户空间设备已添加。

通过这些步骤,设备被完整地注册到内核的设备模型中,并与总线和驱动程序建立了关联。

bus->p->drivers_autoprobe 这个是什么类型?

🤖

在 Linux 内核中,bus->p->drivers_autoprobe 是一个布尔类型(bool),表示是否允许总线自动探测驱动程序与设备之间的匹配关系。


1. 定义位置

drivers_autoprobe 是在 struct bus_type_private 中定义的,bus->p 是指向总线的私有数据结构(struct bus_type_private)的指针。


C

struct bus_type_private { struct kset subsys; // 总线的 kobject 集合 struct kset drivers_kset; // 驱动的 kobject 集合 struct kset devices_kset; // 设备的 kobject 集合 struct klist klist_devices; // 总线上的设备列表 struct klist klist_drivers; // 总线上的驱动列表 bool drivers_autoprobe; // 是否启用驱动自动探测 };

drivers_autoprobe 是一个布尔变量,用来控制是否允许总线自动探测驱动与设备的匹配关系。


2. 作用

drivers_autoprobe 的主要作用是在设备注册到总线时,控制是否自动调用 device_attach() 来尝试匹配设备和驱动。

当 drivers_autoprobe 为 true 时:

  • 内核会在设备注册到总线时自动调用 device_attach()。
  • device_attach() 会遍历总线上的所有驱动,尝试找到与设备匹配的驱动,并调用驱动的 probe() 函数。

当 drivers_autoprobe 为 false 时:

  • 内核不会主动尝试匹配设备与驱动。
  • 驱动与设备的绑定需要开发者手动触发(通常是通过其他机制,如用户空间工具)。

3. 示例:在注册总线时初始化

drivers_autoprobe 的值通常在总线类型注册时初始化。以下是 platform_bus_type 的定义示例:


C

struct bus_type platform_bus_type = { .name = "platform", .match = platform_match, // 设备与驱动的匹配函数 .p = &(struct bus_type_private) { .drivers_autoprobe = true, // 启用自动探测驱动 }, };

在这里,platform_bus_type 的私有数据中,将 drivers_autoprobe 设置为 true,表示 platform 总线支持驱动与设备的自动匹配。


4. 使用场景

drivers_autoprobe 的典型使用场景包括:

  • 自动匹配驱动:
    如果 drivers_autoprobe = true,当设备通过 device_add() 被注册到总线时,内核会自动尝试匹配驱动。
  • 手动匹配驱动:
    如果 drivers_autoprobe = false,设备注册到总线后不会自动匹配,开发者需要手动调用相关函数(如 device_attach())来触发匹配逻辑。

5. 结合 bus_add_device() 的逻辑

当 drivers_autoprobe 为 true 时,device_add() 调用 bus_add_device() 会自动调用 device_attach(),进入设备与驱动的匹配流程:


C

int bus_add_device(struct device *dev) { struct bus_type *bus = dev->bus; int error = 0; // 如果总线允许自动探测,则尝试匹配驱动 if (bus->p->drivers_autoprobe) { error = device_attach(dev); // 自动匹配设备与驱动 } return error; }


6. 小结

  • bus->p->drivers_autoprobe 是一个布尔变量(bool),定义在 struct bus_type_private 中。
  • 它用于控制是否允许总线自动探测设备与驱动的匹配关系。
  • 典型值:
    • true:允许自动探测驱动。
    • false:禁止自动探测驱动,需要手动匹配设备与驱动。

这一机制为总线提供了灵活性,允许开发者根据具体的需求控制驱动匹配行为。

i.MX6ULL平台:深入解析Platform设备与驱动匹配机制 在Linux驱动开发中,设备驱动模型是基础,而Platform虚拟总线为片上外设提供了统一的挂载和管理机制。内核通过设备树中的compatible属性、驱动id_table等匹配规则,将platform_device与platform_driver绑定,并触发probe函数完成初始化。这种机制在嵌入式平台如i.MX6ULL上尤为关键,开发者常因匹配失败导致驱动无法加载。理解匹配优先级与资源获取流程,能显著提升驱动开发效率。本文从概念到实操,解析Platform设备与驱动匹配的完整链路,并结合i.MX6ULL 阅读详情

相关推荐

设备添加的device_add函数详解

在此示例中,我们创建了一个名为“my_device_data”的设备结构体,并将其与之前定义的名为“my_device_driver”的设备驱动程序结合。我们使用platform_driver_register函数来注册驱动程序,并使用device_add函数将设备添加到内核中。在此示例中,我们创建了一个名为“my_device_driver”的设备驱动程序。这个结构体包含设备信息,例如设备名称、设备版本等。在此示例中,我们创建了一个名为“my_device”的设备,并为其指定了一个名称和一个版本号。

qq_37934722的博客 743

linux设备驱动 device add详解

《Linux设备节点创建》内核kobject上报uevent过滤规则_程序改变生活-优快云博客_netlink_kobject_uevent

u012787604的博客 3725

RK3399平台开发系列讲解(内核入门篇)1.12、设备的添加device_add函数详解

文章目录

内核笔记 2510

device_add

八、device_add 强烈建议阅读原文:https://blog.youkuaiyun.com/qq_20678703/article/details/52841706 展开 1.总体框架 linux设备模型:设备device,驱动driver,总线bus。 设备代表物理设备,驱动代表了设备操作方法,bus则是用来管理和匹配它们。 device和driver里面都有一个成员变量bus,表示它们归哪个...

weixin_42082222的博客 1736

開機自動進入UEFI Interactive Shell無法正常開機怎麼辦?

BIOS/UEFI,啟動後進入UEFI Interactive Shell大多數人都告訴你沒有安裝系統去裝系統吧,但你明明昨天還在運行系統?今天就這樣?有沒有解決辦法?

sheaahhoi1的博客 7739

Android 集成 Google 与 Facebook 第三方登录实战详解(2024版)

本文详细介绍了2024年Android应用集成Google与Facebook第三方登录的完整实战指南。通过分步教程和代码示例,帮助开发者快速实现一键登录功能,提升用户体验和注册转化率,同时涵盖隐私合规和常见错误处理的最佳实践。

blue的专栏 822

bus中设备驱动的probe触发逻辑和device、driver的添加逻辑

讲一下linux驱动开发中,内核提供的接口内部是如何去触发驱动程序的probe,以及总线是如何去添加设备和驱动进bus中的(bus_add_device/driver),还有probe函数的触发方式有哪些(手动和自动)

caiji0169的博客 2685

python 常见算法(1-50题)

常见的算法题

weixin_58470558的博客 1756

Linux 总线-设备-驱动(Bus-Device-Driver)完整协作原理

本文深入解析Linux设备驱动模型中的总线-设备-驱动三核心架构。总线(bus_type)作为中介平台,管理设备与驱动的匹配规则、探测及卸载流程。设备(device)描述硬件资源,驱动(driver)包含操作代码但无硬件绑定。两者通过总线自动匹配(如设备树compatible或设备ID),匹配成功则调用驱动的probe函数初始化硬件并创建设备节点。工作流程分为静态加载(设备树优先)和动态热插拔两种场景。该模型实现设备与驱动解耦、多硬件适配和统一生命周期管理,通过sysfs提供可视化调试接口,大幅提升Linu

hkj8808的博客 454

Android14 有线网络静态IP配置:从固件烧录到系统默认设置

本文详细解析了在Android14系统中,如何通过修改系统框架层和设置应用,为设备预设有线网络静态IP地址,实现固件烧录后即具备指定网络配置的功能。文章深入探讨了从扩展SettingsProvider数据库字段、配置默认值,到在设置应用中读取和应用配置的完整流程,旨在解决工业平板、智能终端等设备在无DHCP网络环境中批量部署的痛点,提升开箱即用体验。

lake5的博客 918

RRAM/ Near Memory Computing (NMC) Survey - Reading Notes 0707

Reading Notes of Resistive Random Access Memory – Day 2 Chapter 3 RRAM Characterization and Modeling Overview of RRAM Physical Mechanism A general picture for the filamentary switching mechanism. Forming: 对本征RRAM样本,加电压VformingV_{forming}Vforming​,中间氧化层的O

Blog of Lucky H6 991

Linux platform 设备驱动匹配机制

Linux 中的总线由...这里最关键的是match()和probe()。match()决定一个 device 和一个 driver 是否匹配。PCI bus 根据 vendor/device id 匹配;USB bus 根据 USB id table 匹配;platform bus 可以根据 Device Tree compatible、ACPI id、platform id table、名字匹配;probe()则是匹配成功后的入口。很多 bus 的probe()

日常学习记录 363

C++和蓝图1:Unreal Engine 中 C++ 与蓝图的桥梁

摘要: 本文介绍了Unreal Engine(UE)中C++与蓝图可视化脚本的结合机制,重点解析了宏系统(UCLASS、UPROPERTY、UFUNCTION)如何实现代码与蓝图的交互。相比Unity的纯C#脚本模式,UE的双轨制开发允许程序员用C++处理核心逻辑,同时通过蓝图让非程序员快速迭代。文章对比了两大引擎的编程范式差异,指出UE的反射系统和宏标记提供了更精细的控制,并给出了从Unity迁移到UE的具体思路。核心在于理解UE的混合编程优势:C++保证性能,蓝图提升开发效率,二者通过宏系统无缝协作。

qq_46348216的博客 1407

spi子系统源码——spi_add_device

spi_add_device是SPI 子系统中将 SPI 外设正式接入内核设备模型的核心函数。前面注册了总线和类,通过spi_add_device来添加spi外设。下面具体看怎么实现外设接入内核的。

m0_62688879的博客 687

自动驾驶预测决策规划八股

预测规划八股个人总结。

dawushixiange的博客 479

github创建账号第一步始终出错

github创建账号总结:第一次注册GitHub,填好用户名邮箱密码后进入下一步就卡在哪里,上面还提示Unable to verify your captcha response等,进入网址的解决办法以及下载其他的浏览器也无法解决,用手机浏览器抱着试一试的心态竟然成功了,分享给大家。手机下载谷歌浏览器,进入GitHub正常注册,能向下继续,邮箱验证完以后再用电脑登陆就ok啦

计算机毕业论文源码,学生个人网页制作html源码。贴近用户做网络推广和互联网优化。 4376

基于i.MX6ULL的Platform总线机制解析:设备树匹配与驱动编写实战

Linux设备模型以总线、设备、驱动三大核心组件构建统一管理框架,Platform虚拟总线则专门服务于CPU内部外设这类无真实物理总线的硬件。其核心原理是通过匹配机制将platform_device与platform_driver关联,而设备树则负责描述硬件资源,使驱动代码与具体电路解耦。理解这一机制对嵌入式开发至关重要:它实现了资源动态分配、驱动可移植性以及热插拔支持,尤其适用于i.MX6ULL等ARM平台的外设驱动开发。本文结合i.MX6ULL实际场景,深入剖析Platform设备与驱动的匹配流程,涵盖

weixin_33834075的博客 640

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Linux 设备树(Device Tree)概览

本文是一份系统化的 Linux 设备树(Device Tree)学习与实践指南,覆盖从硬件描述思想、语法规范、内核解析机制到驱动开发实战的完整知识体系。

smallerxuan的博客 6955

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Linux设备驱动模型与 sysfs实现分析以及设计模式应用

这个问题和上一节模块依赖有关,简单点说,建立模块依赖引用计数机制需要在驱动结构体中记录一个struct module指针指向THIS_MODULE,而如果将驱动注册接口定义为纯函数,将无法把环境中的THIS_MODULE带入LINUX驱动核心层赋值给对应字段(不能使用参数的形式传入核心层,因为驱动开发者无需关心THIS_MODULE).距几个例子:而对于那些没有定义成宏的核心驱动注册接口,比如isa_register_driver,用户手填THIS_MODULE是标准做法。

tugouxp的专栏 2103

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

linux设备驱动模型之device

在Linux内核的驱动模型中,​是硬件实体的抽象表示,是驱动管理的核心对象。设备模型通过统一的框架管理硬件资源、设备生命周期以及与用户空间的交互。

浩瀚之水的专栏 1185

Linux驱动开发中probe函数的设备树匹配机制解析

本文解析了Linux驱动开发中probe函数的设备树匹配机制,重点介绍了设备树基础概念、probe函数调用流程及I2C驱动的匹配实现。通过详细的关键属性解析和实战案例,帮助开发者掌握设备树与驱动的动态匹配技术,提升驱动开发效率与可靠性。

189

深入解析Linux V4L2设备节点:从内核驱动到应用调试全流程

在Linux多媒体开发中,设备节点是用户空间与内核驱动交互的核心接口。以字符设备文件形式存在的 `/dev/videoX` 节点,其背后是Video for Linux 2(V4L2)子系统,它定义了视频设备的标准操作框架。理解其工作原理,关键在于掌握 `video_device` 结构体的注册流程、索引分配机制以及 `ioctl_ops` 回调函数的实现。这一机制的价值在于为摄像头、采集卡等视频硬件提供了统一的抽象层,使得应用层可以通过标准API进行图像捕获与处理,广泛应用于嵌入式系统、视频监控和计算机视

cuiji1279的博客 394

驱动二阶段——设备驱动

input子系统的设计旨在实现对于各种输入设备的统一抽象和处理。其主要组成部分包括:1、输入核心层(Input core) 2、输入事件层(Input Events) 3、设备驱动程序层(Input DeviceDriver)Linux内核中注册了多个事件处理handler驱动模块,分别是:evdev:通用输入事件接口,我们可以通过设备文件/dev/eventX或/dev/input/eventX读取事件;mousedev:一个早期的鼠标事件接口;

azwsm的博客 249

总线、设备、驱动模型通用API及数据结构学习

用于在 Linux 内核设备模型中注册一个总线类型。主要作用:为 struct subsys_private 结构体分配内存。设置总线名及相关属性。将总线相关的kset注册进内核设备模型中。添加名为device和driver的kset用于组织连接到总线上的设备和驱动。初始化锁和链表用于管理总线上的驱动与设备subsys_private.bus_notifier 通知链,用于在内核中传递特定事件的通知。

2301_79302469的博客 423

Linux设备驱动开发入门:从内核模块到字符设备与设备树

在嵌入式与物联网时代,Linux设备驱动是连接软件与硬件的关键桥梁。理解内核模块的加载机制、字符设备框架以及设备树匹配原理,是驱动开发的三大基石。设备驱动不仅涉及寄存器操作与中断处理,更需掌握并发同步与内核调试手段,其稳定性直接影响整个系统表现。从PC上的QEMU模拟环境到真实开发板,循序渐进地开展驱动实验,可有效提升工程实践能力。该领域技术栈广泛应用于消费电子、汽车电子与工控场景,人才缺口大、薪资高,但入行门槛也高。本文从基础概念出发,梳理驱动开发的核心原理与实战方法,帮助初学者避开常见陷阱,系统性构建L

weixin_34406086的博客 436

Linux驱动-i2c 驱动框架编写

i2C 驱动框架编写,驱动框架学习法,先写一个框架。既然写框架 基于之前设备树已经配置了,那么写一个基本的框架和设备树节点匹配上。这里就是i2c 驱动框架的一个总结、整理,对于遇到的问题也要有自己的解决问题思路。i2c 框架理解,其实也就是一套平台总线的封装。

十年饮冰,难凉热血 175
上一篇: linux 驱动的platform机制:
下一篇: linux 解析设备树文件时,怎么区分是属于Platform 设备和非Platform 设备1
BlueBirdssh
博客等级 码龄21年 231粉丝 198原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值