Linux驱动入门(6.0)--- Linux驱动与设备的匹配规则

2023-11-01

前言

(1)因为在Linux驱动开发中,驱动可以和设备c文件文件进行匹配,也可以和设备树dts文件进行匹配。为了弄明白驱动与他们的匹配规则,我查阅了一些资料同时阅读了源码,最终打算使用图片的方式形象具体的写成博客。
(2)网上的资料基本都大同小异,都是直接干巴巴的贴出源码,然后一顿分析。而Linux中的调用关系太复杂,很容易看的头晕.
(3)因此我就根据大佬们的分析,对着代码一点一点的慢慢看。最终对驱动与设备的匹配规则有了一定的认识。
(4)通过源码我们可以知道Linux的匹配规则是有5条。但是很多时候,在网上说只有4条,要么就是无视了acpi匹配规则,要么就是无视了设备中的driver_override匹配规则。我也翻阅了正点原子,韦东山,北京迅为的教程,发现他们对这些匹配规则都进行了一定程度的无视。后面我将会讲解为什么会进行无视。

Linux驱动与设备的5条匹配规则

驱动与设备匹配源码

(1)在Linux的平台总线中,我们是使用platform_match()函数进行设备与驱动匹配的。
(2)platform_match()函数定义在文件 drivers/base/platform.c 中,函
数内容如下所示:

static 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);

	/* When driver_override is set, only bind to the matching driver */
	if (pdev->driver_override)
		return !strcmp(pdev->driver_override, drv->name);

	/* Attempt an OF style match first */
	if (of_driver_match_device(dev, drv))
		return 1;

	/* Then try ACPI style match */
	if (acpi_driver_match_device(dev, drv))
		return 1;

	/* Then try to match against the id table */
	if (pdrv->id_table)
		return platform_match_id(pdrv->id_table, pdev) != NULL;

	/* fall-back to driver name match */
	return (strcmp(pdev->name, drv->name) == 0);
}

(3)从上面的代码我们可以看到,有四个if判断,最后那个return 还调用了strcmp()函数进行字符串的对比。因此我们可以得出结论:Linux中,驱动和设备是有5条匹配规则的。

匹配规则1

(1)首先我们需要知道,dev,drv,pdev和pdrv分别代表什么意思。其实我们从他的变量定义就可以看出来。
<1>pdev = platform_device
<2>dev = platform_device.dev
<3>pdrv = platform_driver
<4>drv = platform_driver.driver
(2)由此可见,他首先判断platform_device.driver_override有没有赋值,如果被赋值了无论有没有被匹配上,后面的程序都不会再进行了!
(3)如果platform_device.driver_override被赋值了,那么我们就开始判断platform_device.driver_override == platform_driver.driver.name是否成立。如果成立就匹配成功,否则匹配失败。

if (pdev->driver_override)
	return !strcmp(pdev->driver_override, drv->name);

在这里插入图片描述

匹配规则2

(1)这一条主要是用来与设备树进行匹配的。这里有一个知识点,我们可以看到这个函数是of类型的,前缀是 of 的函数都是用于和设备树进行匹配的。
(2)我们可以看到,这里其实就是platform_driver.driver.of_match_table设备树的compatible 属性进行匹配。(如下图)

static inline int of_driver_match_device(struct device *dev,const struct device_driver *drv)
{
	return of_match_device(drv->of_match_table, dev) != NULL;
}
if (of_driver_match_device(dev, drv))
	return 1;
	

在这里插入图片描述

匹配规则3

(1)这一条很多人都是直接一句ACPI 匹配方式,然后就没有了。一开始我认为是使用的人太少,所以都避而不谈。后面发现是你根本改不了。
(2)ACPI主要用于x86架构的传统PC平台,特别是在桌面和笔记本电脑上。它较为复杂,包含了丰富的系统管理和电源管理功能。开发人员无法修改,只能由主板供应商修改BIOS固件。
(3)所以这个你不用理会。

if (acpi_driver_match_device(dev, drv))
	return 1;

匹配规则4

(1)第4条规则,判断platform_driver.id_table有没有赋值,如果被赋值了无论有没有被匹配上,后面的程序都不会再进行了!
(2)这个说白了就是就是让platform_driver.id_table.name == platform_device.name进行名字匹配,如果名字相同,就匹配成功。

static const struct platform_device_id *platform_match_id(
			const struct platform_device_id *id,
			struct platform_device *pdev)
{
	while (id->name[0]) {
		if (strcmp(pdev->name, id->name) == 0) {
			pdev->id_entry = id;
			return id;
		}
		id++;
	}
	return NULL;
}
if (pdrv->id_table)
	return platform_match_id(pdrv->id_table, pdev) != NULL;

在这里插入图片描述

匹配规则5

(1)这个就是下下策了,platform_device.driver_override和platform_driver.id_table都没有被定义。同时,设备树没有匹配成功。最终才会进行此次匹配。
(2)这个匹配很简单,platform_device.name == platform_driver.driver.name是否相等,如果相等,表示驱动和设备匹配成功。否则驱动和设备彻底匹配失败。

return (strcmp(pdev->name, drv->name) == 0);

在这里插入图片描述

总结

(1)一般来说,我们在驱动的platform_driver结构体只会写两个。
<1>platform_driver.driver.name用于和c文件匹配。
<2>platform_driver.driver.of_match_table 用于和设备树匹配。
(2)注意:如果我们我们只写上面两种匹配方式,那么platform_device.driver_override和platform_driver.id_table都不能赋值!
(3)为什么别人常常说Linux驱动只有4条匹配规则呢?原因很简单,ACPI开发人员无法进行更改,只能由主板供应商修改BIOS固件,所以大家都选择了无视。
(4)为甚很多人会无视driver_override匹配规则呢?很简单,如果driver_override匹配规则被赋值了,那么后面的四条规则都将会失效。所以一般不写这一条。

static struct platform_driver gpio_platform_driver = {
	.driver		= {
		.name	= "100ask_gpio_plat_drv", //用于和设备c文件匹配
		.of_match_table = gpio_dt_ids,  //用于与设备树匹配
	},
	.probe		= gpio_drv_probe,
	.remove		= gpio_drv_remove,
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux驱动入门(6.0)--- Linux驱动与设备的匹配规则 的相关文章

  • Nasm 打印到下一行

    我用 nasm Assembly 编写了以下程序 section text global start start Input variables mov edx inLen mov ecx inMsg mov ebx 1 mov eax 4
  • 在键盘热插拔上加载模块

    我正在尝试学习如何为 Linux 系统编写模块和驱动程序 类似于this https unix stackexchange com questions 120839 usb kernel module does not load on de
  • Mono 和 WebRequest 速度 - 测试

    在 mono 4 6 2 linux 中 我注意到 wget 下载文件的速度与webclient DownloadString 所以我做了一个小测试来调查 为什么 wget 明显比 C 快 根据我自己的实验 使用 wget 下载 手动读取文
  • xdotool 类型需要很长时间并导致整个桌面冻结

    我一直在使用xdotool type过去只能在快捷方式上输入耸肩xdotool type 这可行 但总是需要相当长的时间 并导致整个桌面冻结 完全冻结 而不仅仅是输入 几秒钟 不过并没有太打扰我 现在我需要一种方法来从文件中读取内容 对其进
  • gnome-terminal 新选项卡,使用别名作为要执行的命令

    我已经创建了一个别名 bashrc文件如下 alias myproject cd Desktop myproject 当我重新启动终端时保存文件后 输入myproject带我到项目目录 但是当我尝试使用别名作为新的命令参数时gnome te
  • 如何阅读shell命令的源代码?

    我想阅读编写linux命令的实际源代码 我已经获得了一些使用它们的经验 现在我认为是时候与我的机器进行更深层次的交互了 我在这里找到了一些命令http directory fsf org wiki GNU http directory fs
  • 如何在 Linux 中使用单行命令获取 Java 版本

    我想通过单个命令获取 Linux 中的 Java 版本 我是 awk 的新手 所以我正在尝试类似的事情 java version awk print 3 但这不会返回版本 我将如何获取1 6 0 21从下面的Java版本输出 java ve
  • gdb 错误 - 文件不是可执行格式:无法识别文件格式

    我正在尝试使用 gdb 调试某个名为 xdf 的程序 但是当我运行 gdb xdf 时 出现以下错误 home nealtitusthomas X ray astronomy heasoft 6 24 x86 64 pc linux gnu
  • 如何仅将整个嵌套目录中的头文件复制到另一个目录,在复制到新文件夹后保持相同的层次结构

    我有一个目录 其中有很多头文件 h 和其他 o 和 c 文件以及其他文件 这个目录里面有很多嵌套的目录 我只想将头文件复制到一个单独的目录 并在新目录中保留相同的结构 cp rf oldDirectory newDirectory将复制所有
  • grails 上的同步块在 Windows 上有效,但在 Linux 上无效

    我有一个 grails 应用程序 它依赖于服务中的同步块 当我在 Windows 上运行它时 同步按预期工作 但当我在 ams linux 上运行时 会出现 StaleObjectStateException 该问题在以下示例中重现 cla
  • 如何在 Linux x86_64 上模拟 iret

    我正在编写一个基于 Intel VT 的调试器 由于当 NMI Exiting 1 时 iret 指令在 vmx guest 中的性能发生了变化 所以我应该自己处理vmx主机中的NMI 否则 guest会出现nmi可重入错误 我查了英特尔手
  • Bash 脚本 - 迭代 find 的输出

    我有一个 bash 脚本 其中需要迭代 find 命令输出的每一行 但似乎我正在迭代 find 命令中的每个单词 以空格分隔 到目前为止我的脚本看起来像这样 folders find maxdepth 1 type d for i in f
  • 如何从 Linux 的 shell 中删除所有以 ._ 开头的文件?

    确实如标题所示 我已将许多文件从 Mac 复制到 Raspberry Pi 这导致了许多以前缀开头的多余文件 我想删除以以下开头的文件夹中的每个文件 我该怎么做 尝试类似的方法 cd path to directory rm rf 或者 如
  • 无关的库链接

    我有一个可能有点愚蠢的问题 因为我很确定我可能已经知道答案了 假设你有静态库A 动态共享库B和你的linux下的程序C 假设库 A 调用库 B 中的函数 并且您的程序调用库 A 中的函数 现在假设 C 在 A 中调用的所有函数都不使用 B
  • 如何通过代理将套接字连接到http服务器?

    最近 我使用 C 语言编写了一个程序 用于连接到本地运行的 HTTP 服务器 从而向该服务器发出请求 这对我来说效果很好 之后 我尝试使用相同的代码连接到网络上的另一台服务器 例如 www google com 但我无法连接并从网络中的代理
  • CentOS目录结构是树形的吗?

    CentOS 上有相当于树的东西吗 如果你的 Centos 系统上没有安装 tree 无论如何我通常建议服务器设置使用最小安装磁盘 你应该在命令行中输入以下内容 yum install tree y 如果没有安装 那是因为您没有正确的存储库
  • 如何在 Linux 主机上的 docker 容器中挂载目录 [重复]

    这个问题在这里已经有答案了 我想将一个目录从 docker 容器挂载到本地文件系统 该目录是网站根目录 我需要能够使用任何编辑器在本地计算机上编辑它 我知道我可以跑docker run v local path container path
  • 无法仅在控制台中启动 androidstudio

    你好 我的问题是下一个 我下载了Android Studio如果我去 路径 android studio bin 我执行studio sh 我收到以下错误 No JDK found Please validate either STUDIO
  • 如何查明 Ubuntu 上安装了哪个版本的 GTK+?

    我需要确定 Ubuntu 上安装了哪个版本的 GTK 男人似乎不帮忙 这个建议 https stackoverflow com a 126145 会告诉您安装了哪个 2 0 的次要版本 不同的主要版本将具有不同的包名称 因为它们可以在系统上
  • 将数组传递给函数名称冲突

    Specs GNU bash 版本 3 1 17 无法升级 Premise 我一直在摆弄数组 我想知道是否有任何方法可以让函数的本地变量与所述函数外部的数组同名 Example 在下面的示例中 我将尝试显示该问题 Working bin b

随机推荐

  • Linux运维常用工具软件

    1 远程桌面连接 TigerVNC Xshell 2 FTP服务和客户端 FileZilla 将客户端的文件上传到服务器上 客户端可以使用免费的FileZilla Client 支持多线程上传文件 3 硬件检测 CPU Z CPU Z是一款
  • 2022-12-11 leetcode与蓝桥刷题情况

    一 leetcode题目 今天的leetcode是写的周赛题目 昨天状态不好 摸鱼一天 1 数组中最长的方波 题目描述 给你一个整数数组 nums 如果 nums 的子序列满足下述条件 则认为该子序列是一个 方波 子序列的长度至少为 2 并
  • fullcalendar v6的使用记录

    翻了翻百度 教程很多都过时了 方法都废弃了 这次是以V6版本CDN方式使用说明 文档地址 配置 var calendarConfig 加载 loading function load 可以控制页面的加载状态 app instance dat
  • ctfshow-萌新-web3( 利用intval函数的特性配合联合注入获取网站敏感信息)

    ctf show 萌新模块 web3关 此关卡考察的是 intval 函数的特性 以及SQL注入漏洞的利用 首先需要利用 intval 转换字符串的特性绕过校验 而后利用联合注入获取数据库中的敏感信息 从而获取flag 源码中过滤了or 加
  • Linux内核编译和安装

    下载对应的linux内核源码 The Linux Kernel Archives 2 传输到要安装内核的服务器系统中的对应根目录下 usr src scp p 端口号 源文件 username IP地址 例如 scp p 8090 linu
  • 验证实例的有效性与类型的判断

    我们常常会用到指针变量 指针只有赋值以相应的实例才有意义 怎么判断指针引用实例的有效性是我们经常面对的一个问题 我现在 只知道两种方法 列举如下 1 ASSERT VALID pMyObject ASSERT VALID 要判断的类必须是C
  • PTA-找完数(C语言)

    所谓完数就是该数恰好等于除自身外的因子之和 例如 6 1 2 3 其中1 2 3为6的因子 本题要求编写程序 找出任意两正整数m和n之间的所有完数 输入格式 输入在一行中给出2个正整数m和n 1
  • java field_Java Field.get()取得对象的Field属性值

    首页 gt 基础教程 gt 反射 gt Reflection API Java Field get 取得对象的Field属性值 定义 public Object get Object obj 1 如果字段不是静态字段的话 要传入反射类的对象
  • win10修改系统字体(替换OneNote中Calibri字体)

    微软的OneNote还是很好用的 但是字体问题一直是一个吐槽点 我自己就去微软官网吐槽了好几次 然而并没有什么用 我说设置默认字体为consolas完全无法生效 再次输入笔记时 中文自动改为微软雅黑 英文就是Calibri 他们回复我说确实
  • 递归实现逆序输出(C)

    一 概念 程序调用自身的编程技巧称为递归 recursion 递归做为一种算法在程序设计语言中广泛应用 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法 它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
  • diffusion model(三)—— classifier guided diffusion model

    系列阅读 diffusion model 一 DDPM技术小结 denoising diffusion probabilistic diffusion model 二 DDIM技术小结 diffusion model 三 classifie
  • 公司不重视软件测试,新来的阿里P8给我们撰写了测试用例编写规范

    测试用例 Test Case 是指对一项特定的软件产品进行测试任务的描述 体现测试方案 方法 技术和策略 其内容包括测试目标 测试环境 输入数据 测试步骤 预期结果 测试脚本等 最终形成文档 1 能看懂需求文档 找准测试测试依据 作为测试人
  • 29.手把手系列之二进制部署高可用k8s集群

    29 手把手系列之二进制部署高可用k8s集群 二进制部署高可用k8s集群 本章节采用纯二进制文件方式部署https 证书有效期为10年 高可用k8s集群 所有涉及的配置文件和镜像均已提供 另外 默认集群规模可支撑254个节点 如果需要调整
  • MyBatis自定义映射resultMap

    目录 一 字段名与属性名不一致 方法一 方法二 方法三 二 处理多对一映射关系 1 级联属性赋值 用的不多 虽然简单 2 Association 3 分步查询 三 处理一对多映射关系 1 collection 2 分步查询 一 字段名与属性
  • 《成年人の骚话大全》

    现在的年轻人 骚气得很 不仅为人性格闷骚 网上冲浪时更是满嘴骚话 今天我们来看看 在网民的集体智慧下 究竟有哪一些旧词被 骚 出了新意吧 扫码关注公众号 肉眼品世界 若要问 什么东西能够准地捕捉当代人的复杂想法 同时又能让接受信息的一方快速
  • specCPU 2006 备忘

    前言 首先 specCPU是收费的 好像是800 还是1000 缴费了才有软件分发给你 关键是你要提交结果 那估计得需要购买了 因为测试报告里面有个序列号 应该是购买后给的一个号 测试的时候也要写到配置文件里 但是个人1测试或者普通项目摸底
  • 秒杀多线程第一篇 多线程笔试面试题汇总

    http blog csdn net morewindows article details 7392749
  • linux文件权限修改

    chmod u g o r w x 1 c 权限命令符 第一权限 第二权限 第三权限 加权 减权 唯一权限 读权 写权 可执行权 文件名 总权限 a all 可替换u g o R 4 w2 x1 可以用三个数字设置权限 例如777表示权限全
  • 浏览器窗口切换(从一个页面切换到另一个页面并且不刷新)

    从一个页面跳转到另一个浏览器打开过的页面 只有通过window open 打开的同源页面才能相互切换 window open javascript name 第一项参数 javascript 后可添加js 代码也会执行 第二项参数 name
  • Linux驱动入门(6.0)--- Linux驱动与设备的匹配规则

    前言 1 因为在Linux驱动开发中 驱动可以和设备c文件文件进行匹配 也可以和设备树dts文件进行匹配 为了弄明白驱动与他们的匹配规则 我查阅了一些资料同时阅读了源码 最终打算使用图片的方式形象具体的写成博客 2 网上的资料基本都大同小异