【linux kernel】对linux内核设备的注册机制和查找机制分析
文章目录
- 1、简介
- 2、device_initialize分析
- 3、device_add分析
- 4、总结
🔺【linux内核系列文章】
👉对一些文章内容进行了勘误,本系列文章长期不定时更新,希望能分享出优质的文章!
- 1、《linux内核数据结构分析之哈希表》
- 2、《一文总结linux内核通知链》
- 3、《linux内核中的debugfs》
- 4、《linux内核数据结构分析之链表》
- 5、《linux media子系统分析之media控制器设备》
- 6、《V4L2-PCI驱动程序样例分析(上)》
- 7、《v4l2框架分析之v4l2_fh》
- 8、《 v4l2框架分析之v4l2_subdev》
- 9、《 v4l2框架分析之v4l2_device》
- 10、《v4l2框架分析之video_device》
- 11、《linux内核重要函数 | do_initcalls》
- 12、《Linux设备驱动模型 | bus》
- 13、《linux内核裁剪随想》
- 14、《基于ARM64分析linux内核的链接脚本vmlinux.lds.S》
- 15、《linux内核start_kernel函数的早期操作》
- 16、《start_kernel函数详解系列之proc_caches_init》
- 17、《start_kernel函数详解系列之fork_init》
- 18、《start_kernel函数详解系列之rcu_init》
- 19、《start_kernel函数详解系列之proc_root_init》
- 20、《start_kernel详解系列之【setup_arch】》
- 21、《linux内核如何启动用户空间进程(上)》
- 22、《linux内核如何启动用户空间进程(下)》
- 23、《一文总结linux内核的完成量机制》
- 24、《一文总结linux内核设备驱动的注册和卸载》
- 25、《linux内核的启动加载程序的总结》
- 26、《linux内核入口:head.o》
- 27、《挂载根文件系统之rootfs》
- 28、《mount系统调用剖析》
- 29、《devtmpfs文件系统分析》
- 30、《linux内核的kthreadd线程》
- 31、《linux内核的进程调度—调度策略》
- 32、《linux系统调用实践(Arm架构)》
- 33、《对linux内核__init机制的实践》
- 34、《linux 内核中EXPORT_SYMBOL()分析与实践》
- 35、《linux内核如何挂载根文件系统》
- 36、《linux内核如何唤醒线程》
- 37、《linux内核的init线程》
- 38、《linux内核伪文件系统—sysfs分析》
- 39、《linux 内核设备模型的初始化(上)》
- 40、《linux 内核设备模型的初始化(下)》
- 41、《linux内核伪文件系统—proc分析》
- 42、《linux中断管理—workqueue工作队列》
- 43、《linux中断管理—软中断》
- 44、《linux中断管理 | tasklet》
- 45、《linux中断管理 | 中断管理框架(01)》
- 46、《linux内存管理 | 分配物理内存页面》
- 47、《linux内存管理 | 释放内存页面》
1、简介
本文基于内核源码
4.19.4
分析。
linux内核设备的注册由device_register()
函数完成,这个函数是linux设备驱动模型的核心函数,实现在/drivers/base/core.c中:
在device_register()
函数中,分为两个步骤:
-
(1)调用
device_initialize()
:该步骤用于初始化一个device。 -
(2)调用
device_add()
:该函数用于将device添加到linux内核的device树中。
2、device_initialize分析
该函数接收一个struct device *dev
参数,在该函数中初始化struct device
结构中的几个重要成员:
-
设置
dev->kobj.kset
为device_kset。device_kset
是一个struct kset
类型的全局变量,用于向sysfs文件系统中导出目录:/sys/device/* 。 -
初始化dev中的kobject,并指定与这个对象相关联的ktype为
device_type
。 -
初始化dma_pools链表。
-
初始化struct device中的各种锁:
- 初始化device的电源管理:
-
如果在NUMA下,还会初始化设置device的
numa_node
为-1。 -
接着初始化device下的links中的链表:
在struct device
中的links表示链接到该设备的suppliers和consumers,由struct dev_links_info
表示:
- 设置device下的
links.status
值为DL_DEV_NO_DRIVER
,表示此时还没有对应驱动attach到这个设备。
以上步骤则是device_initialize()
初始化设备时完成的操作。
3、device_add分析
-
(1)调用
get_device(dev)
增加device的引用计数。 -
(2)如果
dev->p
为NULL,则调用device_private_init()
设置device的私有数据:
- (3)设置device的name:
如果开启支持
pr_debug()
函数,则会打印出对应的设备名称。
- (4)寻找父设备和父设备对应的kobj,并调用kobject_add()将dev->kobj添加到dev->kobj.parent:
- (5)使用
device_create_file
为device创建sysfs属性文件:
error = device_create_file(dev, &dev_attr_uevent);
dev_attr_uevent
是一个struct device_attribute
类型的数据,该结构用于描述导出设备属性的接口,定义如下:
struct device_attribute {struct attribute attr;ssize_t (*show)(struct device *dev, struct device_attribute *attr,char *buf);ssize_t (*store)(struct device *dev, struct device_attribute *attr,const char *buf, size_t count);
};
- (6)添加类的符号链接:
error = device_add_class_symlinks(dev);
device_add_class_symlinks()
的功能是将设备添加到指定的设备类中,并在/sys/class目录下为设备创建符号链接,以便用户空间程序能够方便地访问和管理设备。
- (7)调用
device_add_attrs()
为设备添加属性:
error = device_add_attrs(dev);
device_add_attrs()
的功能是为设备添加属性,并在/sys/devices目录下创建相应的属性文件。这样,用户空间程序可以通过访问设备的属性文件来读取和修改设备的属性值。这个函数在设备驱动的初始化过程中常常被调用,以确保设备的属性能够正确地显示和访问。
- (8)调用
bus_add_device()
添加设备到bus:
bus_add_device
用于将设备添加到总线上。它的功能是将一个设备(struct device
结构体)添加到指定总线(struct bus_type
结构体)上,并进行相应的初始化和注册操作。
bus_add_device
的执行逻辑:
- (1)从
dev->bus
中取得bus_type*
类型的指针bus,如果获取bus不成功,则函数直接返回;如果bus获取成功,则会继续后续的第(2)步操作。- (2)调用
device_add_attrs
接口,将由bus->dev_attrs指针定义的默认attribute添加到内核中,这个操作会体现在sysfs文件系统中的/sys/devices/xxx/xxx_device/目录中。- (3)调用
device_add_groups
将bus_dev_groups
添加到内核中。- (4)调用
sysfs_create_link
将该设备在sysfs中的目录,链接到该bus的devices目录下- (5)接着依然调用
sysfs_create_link
,在该设备的sysfs目录中,创建一个指向该设备所在bus目录的链接,命名为subsystem。- (6)前面几个操作实则是向sysfs文件系统注册关于设备的信息,向用户空间抛出接口。最后步骤则是调用
klist_add_tail()
将该设备指针保存到bus->p->klist_devices
中。
-
(9)调用
device_pm_add()
将一个设备添加到PM核心的active
设备链表中。 -
(10)创建设备节点:
- (11)通过bus_notifier告知系统设备已经添加:
- (12)调用
bus_probe_device()
为该设备probe一个驱动。该函数实现如下:
具体执行流程如下:
- (1)从dev中解析出该dev所在而bus,如果bus不存在,则退出该函数。
- (2)如果设置了
driver_autoprobe
,则调用device_initial_probe(dev)
。该函数本质调用到device_attach()
,尝试将设备连接到驱动程序。- (3)遍历bus上的子系统接口链表
interfaces
,如果add_dev
函数指针存在,则调用对应的函数。(从源码来看有些驱动程序,会使用struct subsys_interface
来实现,在此处实现对注册的subsys_interface
下的add_dev
的调用执行)
- (13)如果父设备存在,则会将该设备添加到父设备的
klist_children
链表中(klist_children
是包含此设备的所有子节点的链表):
- (14)如果设备的class不为NULL,则会将class绑定到device:
klist_add_tail(&dev->p->knode_class,&dev->class->p->klist_devices);
- (15)通知所有的interface接口:
在内核中,struct class_interface
是用于表示设备类和设备驱动之间的接口的结构体。它定义了设备类与设备驱动之间的关联关系,允许设备驱动在注册时与相应的设备类进行关联,并提供了一组函数指针,用于设备类调用设备驱动中的操作。
struct class_interface
结构体定义如下:
struct class_interface {struct list_head node;struct class *class;int (*add)(struct device *dev, struct class_interface *class_intf);void (*remove)(struct device *dev, struct class_interface *class_intf);
};
node
: 用于将struct class_interface
链接到设备类的接口链表中。class
: 指向与该接口相关联的设备类。add
: 指向设备类调用设备驱动的添加操作的函数指针。当设备添加到设备类时,会调用此函数。remove
: 指向设备类调用设备驱动的移除操作的函数指针。当设备从设备类中移除时,会调用此函数。
通过使用struct class_interface
,设备驱动可以与设备类进行交互,以便在设备添加或移除时执行相应的操作。这种机制允许设备驱动与设备类解耦,使得设备驱动可以在设备类的上下文中执行一些操作,而无需直接操作设备类。
回到device_add()
中,使用了list_for_each_entry()
遍历interfaces
链表,如果设置了class_intf->add_dev
,则调用该回调函数指针指向的函数。
4、总结
结合本文内容和linux内核源码,得出以下结论:
-
(1)在设备驱动模型中,所有的设备注册操作最后都会调用
device_register()
函数实现。 -
(2)在笔者分析的linux版本下的
device_register()
中,存在两个数据结构:struct class_interface
和struct subsys_interface
。从内核源码来看,这两个结构只在为数不多的几个特定的驱动程序中使用,具体有什么特殊目的咱不所知,猜测可能是linux内核历史发展遗留下来的代码,在device_register
中仍然保留了对这部分代码的支持。 -
(3)在
device_register()
中调用了bus_probe_device()
,从而证明在注册设备的时候发生了**『设备与驱动匹配』**的过程。
相关文章:
【linux kernel】对linux内核设备的注册机制和查找机制分析
文章目录 1、简介2、device_initialize分析3、device_add分析4、总结 🔺【linux内核系列文章】 👉对一些文章内容进行了勘误,本系列文章长期不定时更新,希望能分享出优质的文章! 1、《linux内核数据结构分析之哈希表》…...
asp.net酒店餐饮管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
一、源码特点 asp.net酒店餐饮管理系统是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c#语言 开发 ASP.NE 酒店餐饮管理系统 二、功能…...
38_Nginx 启动流程
文章目录 src/core/nginx.cint ngx_cdecl main(int argc, char *const *argv) {ngx_buf_t *b;...
数据特征选择 | Lasso特征选择(Python)
文章目录 效果一览文章概述源码设计小结效果一览 文章概述 Lasso算法是一种经典的线性回归算法,被广泛应用于特征选择和降维问题。相较于传统的线性回归算法,Lasso算法能够在保持预测准确性的同时,自动筛选出对目标变量影响较大的特征变量,从而达到降低模型复杂度、提高泛化…...
最小覆盖子串[困难]
优质博文:IT-BLOG-CN 一、题目 给你一个字符串s、一个字符串t。返回s中涵盖t所有字符的最小子串。如果s中不存在涵盖t所有字符的子串,则返回空字符串"" 。 对于t中重复字符,我们寻找的子字符串中该字符数量必须不少于t中该字符数量…...
保姆级搭建Mysql 并进行视图可视化操作
安装MySQL数据库 选择mysql5.7.36_x32.msi”,双击运行,如下图所示: 在此窗口中,选择“Custom”选项,点击“Next>”进入下一步; 在此窗口中,选择号下的MySQL Server 5.7.36 – x64&…...
设计模式的学习顺序
设计模式的学习顺序可以按照以下步骤进行: 掌握基础知识:先确保你对编程语言和软件开发的基本概念有深入的理解,包括面向对象编程、继承、多态等。学习常用设计模式:首先学习并理解一些常用的设计模式,例如单例模式、…...
数据结构和算法——树结构
二叉树 又叫二叉排序树。 节点是数量为,,n为层数。 满二叉树:所有的叶子节点都在最后一层。 完全二叉树:如果所有叶子节点都在最后一层和倒数第二层,而且每个叶子节点都有左右子节点。 完全二叉树 前序遍历 1、先输…...
【Java】Integer包装类
Integer:对基本数据类型 int 实现包装 方法名称说明public Integer(int value)根据 int 值创建 Integer 对象(JDK9以后过时)public integer(String s)根据 String 值创建 Integer 对象…...
Web后端开发登录校验及JWT令牌,过滤器,拦截器详解
如果用户名正确则成功进入 登录功能 代码 Controller Service Mapper 结果 若登录成功结果如下: 如果登录失败,结果如下 登录校验 为什么需要登录校验 有时再未登录情况下, 我们也可以直接访问部门管理, 员工管理等功能 因此我们需要一个登录校验操作, 只有确认用户登录…...
大语言模型迎来重大突破!找到解释神经网络行为方法
前不久,获得亚马逊40亿美元投资的ChatGPT主要竞争对手Anthropic在官网公布了一篇名为《朝向单义性:通过词典学习分解语言模型》的论文,公布了解释经网络行为的方法。 由于神经网络是基于海量数据训练而成,其开发的AI模型可以生成…...
zabbix内置宏、自动发现与注册
一、zabbix内置宏 1、概念: 在Zabbix中,内置宏是一种特殊的变量,通常用在 Trigger 名称和表达式中,引用有关监控对象的信息。 2、种类: {HOST.NAME} 主机名 {HOST.IP} 主机 IP 地址 {TRIGGER.DESCRIPTION} 触…...
Oracle与Mysql语法区别
database 一、数据类型二、update..select语句三、upsert语句四、常见函数五、自动更新列时间戳一、数据类型 OracleMysqlnumberint/decimal变长字符:varchar2varchardatedatetime/timestampinttinyint/smallint/mediumint/int/bigint二、update…select语句 Oracle update t…...
Jetpack:008-Icon与Image
文章目录 1. 概念介绍2. 使用方法2.1 Icon2.2 Image 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack中与Button相关的内容,本章回中主要I con与Image。闲话休提,让我们一起Talk Android Jetpack吧! 1. 概念介绍 我们在本章回中介绍…...
参数解析(牛客)
目录 一、题目 二、代码 一、题目 二、代码 #include <iostream> #include <vector> using namespace std;int main() {string s;getline(cin, s);int i 0;vector<string>ret;while (i < s.size()){if (s[i] )//遇到空格直接跳过{i;}else if (s[i] …...
Linux网络编程系列之服务器编程——阻塞IO模型
Linux网络编程系列 (够吃,管饱) 1、Linux网络编程系列之网络编程基础 2、Linux网络编程系列之TCP协议编程 3、Linux网络编程系列之UDP协议编程 4、Linux网络编程系列之UDP广播 5、Linux网络编程系列之UDP组播 6、Linux网络编程系列之服务器编…...
排序算法-基数排序法(RadixSort)
排序算法-基数排序法(RadixSort) 1、说明 基数排序法与我们之前讨论的排序法不太一样,并不需要进行元素之间的比较操作,而是属于一种分配模式排序方式。 基数排序法比较的方向可分为最高位优先(Most Significant Di…...
nginx绑定tomcat与tomcat联合使用的配置(nginx反向代理tomcat的配置说明)
nginx反向代理tomcat通信配置 (内容来自网上,注解部分才是原创) 切记: url的意思就是 unifed resource location 统一资源定位 其中location就是定位的意思 所以上文中的location就有 对应匹配的 url 标识的资源的相关配置之…...
【Java】nextInt()后面紧接nextLine()读取不到数据/InputMismatchException异常的解决方案
错误如下: 有时候还会抛出InputMismatchException异常 看!我只输入了一个5,并没有给str赋值,它就已经将结果打印出来了!这就意味着,str是读取到了数据的,只不过这个数据并不是我们想要的输入的…...
【传输层协议】UDP/TCP结构特点与原理(详解)
文章目录 1. UDP1.1 UDP结构1.2 UDP特点1. 无连接2. 不可靠3. 面向数据报4. 缓冲区5. 大小受限6. 无序性 2. TCP2.1 TCP结构2.2 TCP特点1. 有连接2. 可靠性3. 面向字节流4. 拥塞控制5. 头部开销 2.3 TCP原理1. 确认应答(安全机制)2. 超时重传(…...
哪种网站适合物理服务器
哪种网站适合物理服务器 看到独立服务器这一词语,相信大家脑海立马就浮现出了它的种种优势,但是有优势就伴随着也有一定的弊端,比如说它的空间大、特殊的的组件配置,权限配置等,但是成本却非常的高,那么我…...
uni-app集成使用SQLite
一、打开uni-app中SQLite 二、封装sqlite.js module.exports {dbName: chat, // 数据库名称dbPath: _doc/chat.db, // 数据库地址,推荐以下划线为开头 _doc/xxx.db/*** Description: 创建数据库 或 有该数据库就打开* author: ZXL* createTime: 2023-10-12 09:23:10* Copyr…...
Qt不能安装自己想要的版本,如Qt 5.15.2
使用在线安装工具安装Qt5.15.2时,发现没有Qt 5的相关版本,只有Qt 6的版本,这时选择右边的Archive,再点击筛选,这时就会出现之前的Qt版本。...
学信息系统项目管理师第4版系列28_组织级项目管理和量化项目管理
1. OPM 1.1. 旨在确保组织开展正确项目并合适地分配关键资源 1.1.1. 有助于确保组织的各个层级都了解组织的战略愿景、实现愿景的措施、组织目标以及可交付成果 1.2. 业务评估是建立OPM框架的必要组件 1.3. OPM3 是组织级项目管理成熟度模型,可用于评估组织项目…...
Bean实例化的三级缓存
在Spring框架中,Bean实例化的三级缓存(三级缓存也称为三级缓存机制)是用于缓存Bean定义的一种机制,用于管理和加速Spring容器中Bean的创建和初始化过程。三级缓存包括了singletonObjects、earlySingletonObjects 和 singletonFact…...
Jenkins+Gitlab+Docker(Dockerfile)部署
Docker部署运行 上一篇内容中使用Jenkins(运行服务器)Gitlab(代码存储库)Webhook(网络钩子)的方式部署运行我们的项目。需要我们在服务器上做好很多相关的环境配置及依赖。 那么假如有这样一个场景:需要把不同技术栈的项目部署到同一台服务器上运行。比如PH…...
Web前端-Vue2+Vue3基础入门到实战项目-Day4(组件的三大组成部分, 组件通信, 案例-组件版小黑记事本, 进阶语法)
Web前端-Vue2Vue3基础入门到实战项目-Day4 组件的三大组成部分(结构/样式/逻辑)scoped样式冲突data是一个函数 组件通信组件通信语法父传子子传父props详解什么是propsprops检验props与data的区别 非父子(扩展)事件总线 (event bus)provide - inject 案例 - 小黑记事本(组件版)…...
【大模型应用开发教程】01_大模型简介
C1 大模型简介 一. 什么是LLM(大语言模型)?1. 发展历程2. 大语言模型的概念LLM的应用和影响 二、大模型的能力和特点1. 大模型的能力1.1 涌现能力(emergent abilities)1.2 作为基座模型支持多元应用的能力1.3 支持对话…...
Flume 简介及基本使用
1.Flume简介 Apache Flume 是一个分布式,高可用的数据收集系统。它可以从不同的数据源收集数据,经过聚合后发送到存储系统中,通常用于日志数据的收集。Flume 分为 NG 和 OG (1.0 之前) 两个版本,NG 在 OG 的基础上进行了完全的重构…...
行业追踪,2023-10-11
自动复盘 2023-10-11 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...
怎么删除wordpress插件/北京seo薪资
Web 的攻击技术 针对 Web 的攻击技术 1.HTTP 不具备必要的安全功能 2.在客户端即可篡改请求 3.对Web应用的攻击模式 主动攻击被动攻击 以服务器为目标的主动攻击 主动攻击(active attack)是指攻击者通过直接访问 Web 应用,把攻击代码传入的…...
网页游戏传奇图片/北京seo优化外包
在使用数组元素时一定要注意元素是否存在,如果不存在,会发出Notice: Undefined offset,$bb [];echo $bb[0];会抛出Notice: Undefined offset: 0 in /usr/local/var/www/aa.php on line 8正确写法 $bb [];echo isset($bb[0]) ? $bb[0] : null; 转载于:https://www.cnblogs.co…...
企业网站怎么做的更好/seo搜索引擎优化ppt
华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不要…...
网上做名片的网站/太仓seo网站优化软件
js中confirm提示三个按钮“是”“否”“取消” 重载DOM中confirm window.confirm function(str) { strstr.replace(/\/g, "&chr(39)&").replace(/\r\n|\n|\r/g, "&VBCrLf&"); execScript("n msgbox(" …...
重庆做网站公司有哪些/网络营销的十大特点
编写Android程序,离不开和Http打交道。android 的单线程UI模型,使得处理Http这样,耗时的操作的操作变得麻烦。传统的作法有Thread Handler和AsyncTask 而这两种方式都是需要自己写很多重复的代码如创建HttpClient etc.不符合DRY(Dont repeat…...
wordpress页面加载时间/链接地址
使用VC编译C或者C程序,都需要相关的C runtime库才能运行。如果你是VC6,相应的库就叫MSVCR,如果是VC2005,那就是MSVCR08,VC2008就是MSVCR09。我这 里假设你安装的是VC2005,请进入如下目录:{VS In…...