RK3568驱动指南|第九篇 设备模型-第101章 总线注册流程理论分析实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第九期_设备模型_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第101章 总线注册流程理论分析实验

在上个章节中,我们成功地在总线目录下创建了属性文件,为总线添加了额外的信息和控制选项。现在,在本章节中,我们将深入分析总线注册的流程,从代码的层面来理解总线的实现过程。通过这样的分析,我们将更好地理解总线注册的内部机制,并能够应用这些知识来实现更复杂的总线功能。让我们深入代码,一起学习总线注册的流程吧!

101.1 bus_register函数解析

开发板上电,我们进入到开发板的/sys/bus/mybus目录下。  

                                                           图101-1

如上图所示,为什么在sys/bus目录下会生成mybus目录以及对应的devices,drivers,drivers_autoprobe,drivers_probe,uevent目录和属性呢?

在开发板/sys目录下的目录都对应一个kobject,所以我们猜测mybus目录和devices,drivers目录和kobject有关系的。而kobject一般要嵌入到其他结构体中去使用。如下图所示,kobject嵌入到device结构体中。                                                             

图101-2

在struct device结构体中包含了kobject结构体,而struct bus_type结构体又包含了struct device结构体。如下图所示:                                                                          图101-3

所以我们猜测这些/sys/bus/下的目录是和struct device结构体中的kobj有关系。接下来我们追踪bus_register函数,函数原型如下所示:

                                                             

/*bus_register - 注册一个驱动核心子系统@bus: 要注册的总线注册总线时,首先将总线与 kobject 基础设施关联起来,然后注册属于该总线的子系统:归属于该子系统的设备和驱动程序。
*/
int bus_register(struct bus_type *bus)
{
int retval;
struct subsys_private *priv;
struct lock_class_key *key = &bus->lock_key;// 分配并初始化一个 subsys_private 结构体,用于保存子系统的相关信息
priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;priv->bus = bus;
bus->p = priv;// 初始化一个阻塞通知链表 bus_notifier
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);// 设置子系统的名称
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
if (retval)
goto out;// 设置子系统的 kset 和 ktype
priv->subsys.kobj.kset = bus_kset;
priv->subsys.kobj.ktype = &bus_ktype;
priv->drivers_autoprobe = 1;// 注册子系统的 kset
retval = kset_register(&priv->subsys);
if (retval)
goto out;// 在总线上创建一个属性文件
retval = bus_create_file(bus, &bus_attr_uevent);
if (retval)
goto bus_uevent_fail;// 创建并添加 "devices" 子目录的 kset
priv->devices_kset = kset_create_and_add("devices", NULL, &priv->subsys.kobj);
if (!priv->devices_kset) {
retval = -ENOMEM;
goto bus_devices_fail;
}// 创建并添加 "drivers" 子目录的 kset
priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);
if (!priv->drivers_kset) {
retval = -ENOMEM;
goto bus_drivers_fail;
}// 初始化接口链表、互斥锁和设备/驱动的 klist
INIT_LIST_HEAD(&priv->interfaces);
__mutex_init(&priv->mutex, "subsys mutex", key);
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&priv->klist_drivers, NULL, NULL);// 添加驱动探测文件
retval = add_probe_files(bus);
if (retval)
goto bus_probe_files_fail;// 添加总线的属性组
retval = bus_add_groups(bus, bus->bus_groups);
if (retval)
goto bus_groups_fail;// 打印调试信息,表示总线注册成功
pr_debug("bus: '%s': registered\n", bus->name);
return 0;bus_groups_fail:
remove_probe_files(bus);
bus_probe_files_fail:
kset_unregister(bus->p->drivers_kset);
bus_drivers_fail:
kset_unregister(bus->p->devices_kset);
bus_devices_fail:
bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail:
kset_unregister(&bus->p->subsys);
out:
kfree(bus->p);
bus->p = NULL;
return retval;
}
EXPORT_SYMBOL_GPL(bus_register);
*/

                     

以下是该函数的主要步骤:

1 分配并初始化一个 subsys_private 结构体,该结构体用于保存子系统的相关信息。

2 将 bus 结构体与 subsys_private 关联起来。

3 初始化一个阻塞通知链表 bus_notifier。

4 通过 kobject_set_name() 设置子系统的名称。

5 设置子系统的相关属性,如 kset 和 ktype。

6 注册子系统的 kset。

7 创建并添加 "devices" 和 "drivers" 两个子目录的 kset。

8 初始化子系统的接口链表、互斥锁和设备/驱动的 klist。

9 添加驱动探测文件。

10 添加总线的属性组。

11 打印调试信息,表示总线注册成功。

接下来我们对上述步骤进行补充讲解。

在步骤1 中,出现了新的结构体:struct subsys_private,如下所示:

struct subsys_private {struct kset subsys;struct kset *devices_kset;struct list_head interfaces;struct mutex mutex;struct kset *drivers_kset;struct klist klist_devices;struct klist klist_drivers;struct blocking_notifier_head bus_notifier;unsigned int drivers_autoprobe:1;struct bus_type *bus;struct kset glue_dirs;struct class *class;
};

struct subsys_private 是一个结构体,用于保存驱动核心子系统(bus)的私有信息。每个子系统都可以有私有数据,这些私有数据存储在struct subsys_private结构体中。那么什么是子系统呢?

在Linux中,子系统是一种机制,用于将特定功能的实现抽象为一个独立的实体。它提供了一种方便的方式,将相关的代码和数据结构组织在一起,以实现特定的功能。子系统可以被视为一个功能模块,它封装了相关的功能和操作,使得用户和应用程序可以通过统一的接口与其交互。

在Linux中,存在许多常见的子系统,每个子系统都负责实现特定的功能。以下是一些常见的子系统示例。

  • 虚拟文件系统(VFS)子系统:VFS子系统提供了对不同文件系统的统一访问接口,使得应用程序可以透明地访问各种文件系统(如ext4、NTFS、FAT等),而无需关心底层文件系统的具体实现。
  • 设备驱动子系统:设备驱动子系统管理和控制硬件设备的驱动程序。它提供了与硬件设备交互的接口,使得应用程序可以通过驱动程序与设备进行通信和控制。
  • 网络子系统:网络子系统负责管理和控制网络相关的功能。它包括网络协议栈、套接字接口、网络设备驱动程序等,用于实现网络通信和网络协议的处理。
  • 内存管理子系统:内存管理子系统负责管理系统的物理内存和虚拟内存。它包括内存分配、页面置换、内存映射等功能,用于有效地分配和管理系统的内存资源。
  • 进程管理子系统:进程管理子系统负责管理和控制系统中的进程。它包括进程的创建、调度、终止等功能,以及进程间通信的机制,如信号、管道、共享内存等。
  • 电源管理子系统:电源管理子系统负责管理和控制系统的电源管理功能。它可以用于控制电源的开关、电源模式的切换、节能功能的实现等。
  • 文件系统子系统:文件系统子系统负责管理和控制文件系统的创建、格式化、挂载、数据存取等操作。它支持各种文件系统类型,如ext4、FAT、NTFS等。
  • 图形子系统:图形子系统负责管理和控制图形显示功能,包括显示驱动程序、窗口管理、图形渲染等。它提供了图形界面的支持,使得用户可以通过图形方式与计算机交互。

在步骤2中,priv->bus = bus;将priv结构体中的bus成员设置为当前注册的总线。这样做的目的是将bus成员与当前总线建立关联。通过将bus成员设置为当前总线,priv结构体可以获取并访问与该总线相关的信息和功能。这种关联可以使priv结构体在操作当前总线时更加方便和高效。

在步骤2 中,bus->p = priv;将priv结构体指针存储在当前注册的总线结构体的成员p中,目的是让当前注册的总线结构体能够快速地找到并访问与之关联的priv结构体。通过将priv结构体指针存储在总线结构体的成员中,总线可以轻松地获取与之相关的私有数据结构。这种关联使得总线能够直接访问和操作与特定总线相关的数据和功能,而无需通过其他方式来查找或传递指针。

在步骤8中,klist_init函数用于初始化两个内核链表(klist),分别是priv->klist_devices和priv->klist_drivers。

  • klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);这行代码初始化了名为priv->klist_devices的内核链表。klist_devices_get和klist_devices_put是两个回调函数,用于在向链表添加或移除元素时执行相应的操作。通常,这些回调函数用于在链表中的每个元素被引用或释放时执行额外的操作。例如,当设备被添加到链表时,klist_devices_get函数可能会增加设备的引用计数;当设备从链表中移除时,klist_devices_put函数可能会减少设备的引用计数。
  • klist_init(&priv->klist_drivers, NULL, NULL);这行代码初始化了名为priv->klist_drivers的内核链表,但与第一个初始化不同,这里没有提供回调函数。因此,这个链表在添加或移除元素时不会执行额外的操作。这种情况下,链表主要用于存储驱动程序对象,而不需要附加的处理逻辑。

通过分析bus_register函数,我们对设备模型有了更深层次的感悟,如下所示:

1.kobject和kset是设备模型的基本框架,它们可以嵌入到其他结构体中以提供设备模型的功能。kobject代表设备模型中的一个对象,而kset则是一组相关的kobject的集合。

2. 属性文件在设备模型中具有重要作用,它们用于在内核空间和用户空间之间进行数据交换。属性文件可以通过sysfs虚拟文件系统在用户空间中表示为文件,用户可以读取或写入这些文件来与设备模型进行交互。属性文件允许用户访问设备的状态、配置和控制信息,从而实现了设备模型的管理和配置。

3. sysfs虚拟文件系统在设备模型中扮演关键角色,它可以将设备模型的组织层次展现出来。通过sysfs,设备模型中的对象、属性和关系可以以目录和文件的形式在用户空间中表示。这种组织形式使用户能够以层次结构的方式浏览和管理设备模型,从而方便地获取设备的信息、配置和状态。sysfs提供了一种统一的接口,使用户能够通过文件系统操作来与设备模型进行交互,提供了设备模型的可视化和可操作性。

   


                                                                                                                   

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

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

相关文章

力扣hot100 二叉树展开为链表 递归 特殊遍历

👨‍🏫 题目地址 👩‍🏫 参考题解 😋 将左子树插入到右子树上 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* …

C/C++动态内存分配 malloc、new、vector(简单讲述)

路虽远,行则将至 事虽难,做则必成 今天来主要讲C中动态内存分配 其中会穿插一些C的内容以及两者的比较 如果对C语言中的动态内存分配还不够理解的同学 可以看看我之前的博客:C语言动态分配 在讲解C的动态内存分配之前 我们先讲一下C内存模型 &#xff1…

CSS免费在线字体格式转换器 CSS @font-face 生成器

今天竟意外发现的一款免费的“网页字体生成器”,功能强大又好用~ 工具地址:https://transfonter.org/ 根据你设置生成后的文件预览: 支持TTF、OTF、WOFF、WOFF2 或 SVG字体格式转换生成,每个文件最大15MB。转换完成以后还会生成一…

宏集PC Runtime软件助推食品行业生产线数字化革新

一、前言 近年来,中国食品行业发展迅速且灵活多变,在当前经济下行的情形下,食品行业正面临着日益激烈的竞争,导致企业利润下降。 为了保持企业市场竞争力,国内某top10食品企业采用宏集SCADA解决方案—PC Runtime软件…

数学公式编译器MathType下载与安装

下载网址:下载 MathType - WIRIS Store 1.点击【下载MathType for Windows】 2、点击中文版 3.找到所下载的目录: 右击-->以管理员身份运行 4、新建word文档 点击文件->账户->关于word 5.点击【文件】、【选项】,❶点击【加载项】…

有趣的数学 为什么素数在密码学中很重要?

这里我们将探讨为什么素数在密码学中很重要。我们将根据特定的密码系统( RSA 算法)来进行深入了解。 一、素数的特殊性 每个数字都可以分解为它的素数。一般来说,找到一个数的因数是非常困难的。要找到一个自然数的所有素因数,必…

Zookeeper 分布式服务协调治理框架介绍入门

文章目录 为甚么需要Zookeeper一、Zookeeper 介绍1.1 介绍1.2 Zookeeper中的一些概念1.2.1 集群角色1.2.2 会话 session1.2.3 数据节点 Znode1.2.4 版本1.2.5 事件监听器 Watcher1.2.6 ACL 权限控制表(Access Control Lists) 二、 Zookeeper的系统模型2.1.1 ZNode节点2.1.2 ZNo…

基于ssm的班级事务管理系统+vue论文

摘 要 在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之前的纸张记录模式已经不符合当前使用要求了。所以,对班级事务信息管理的提升&#x…

【LeetCode:114. 二叉树展开为链表 | 二叉树 + 递归】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

STM32 基础知识(探索者开发板)--135讲 ADC转换

ADC定义: ADC即模拟数字转换器,英文详称 Analog-to-digital converter,可以将外部的模拟信号转换 ADC数模转换中一些常用函数: 1. HAL_ADC_Init 函数 HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc); 初始化ADC 形参&…

后端主流框架-SpringMvc-day2

Java中的文件下载 2 文件下载 文件下载:就是将服务器(表现在浏览器中)中的资源下载(复制)到本地磁盘; 2.1 前台代码 前台使用超链接,超链接转到后台控制器,在控制器通过流的方式…

AI:111-基于深度学习的工业设备状态监测

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

技术与艺术的完美结合,AI艺术字生成平台一览

在创作的世界里,文字不仅是沟通的桥梁,更是灵魂的画笔。有时,我们的海报需要一丝文案的点缀,一些充满艺术感的文字,为作品注入更多的情感与深度。除了手写的文字,AI艺术字为我们提供了新的可能。AI生成未来…

CF1909_C. Heavy Intervals题解

CF1909_C. Heavy Intervals题解 题目传送门(Problem - C - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1909/problem/C)。 题目翻译如下:(图片来源&a…

操作系统期末复习!

引论及进程管理 1.操作系统的主要功能有( )。 A.进程管理、存储器管理、设备管理、处理机管理 B.虚拟存储管理、处理机管理、进程管理、文件管理 C.处理机管理、存储器管理、设备管理、文件管理 D.进程管理、中断管理、设备管理、文件管理 2.操作系统是对( )进行管…

助力工业生产“智造”,基于YOLOv8全系列模型【n/s/m/l/x】开发构建纺织生产场景下布匹瑕疵检测识别系统

纯粹的工业制造没有办法有长久的发展过程,转制造为全流程全场景的生产智造才是未来最具竞争力的生产场景,在前面的开发实践中我们已经涉足工业生产场景下进行了很多实地的项目开发,如:PCB电路板缺陷检测、焊接缺陷检测、螺母螺钉缺…

系列十、Spring Cloud Gateway

一、Spring Cloud Gateway 1.1、概述 Spring Cloud全家桶中有个很重要的组件就是网关,在1.x版本中采用的是Zuul网关,但是在2.x版本中,由于Zuul的升级一直跳票,Spring Cloud最后自己研发了一个网关替代Zuul,即&#xf…

ASP.NET Core基础之图片文件(一)-WebApi图片文件上传到文件夹

阅读本文你的收获: 了解WebApi项目保存上传图片的三种方式学习在WebApi项目中如何上传图片到指定文件夹中 在ASP.NET Core基础之图片文件(一)-WebApi访问静态图片文章中,学习了如何获取WebApi中的静态图片,本文继续分享如何上传图片。 那么…

详谈电商网站建设的四大流程!

在21世纪的互联网时代,电商网站的建设是每个企业发展不可缺少的一次机遇。企业商城网站建设成功也许会获得更大的了利润;如果网站建设不成功,那么也会带来一定的损失。所以建设电商网站不是那么一件简单的事情。那么电商网站制作流程是怎样的…

C++_find 统计一个单词 在一段文中出现的次数

注解: 使用y.find(x, n)从位置n开始在字符串y中查找子串x首次出现的位置。如果找到了子串x,则find()函数会返回该子串在y中的起始索引(位置),否则返回-1(或npos)表示未找到。当find()函数返回非-1值时&…