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

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

前言

(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,
};


相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
目录
相关文章
|
1月前
|
Unix Linux Shell
linux入门!
本文档介绍了Linux系统入门的基础知识,包括操作系统概述、CentOS系统的安装与远程连接、文件操作、目录结构、用户和用户组管理、权限管理、Shell基础、输入输出、压缩打包、文件传输、软件安装、文件查找、进程管理、定时任务和服务管理等内容。重点讲解了常见的命令和操作技巧,帮助初学者快速掌握Linux系统的基本使用方法。
65 3
|
2月前
|
机器学习/深度学习 Linux 编译器
Linux入门3——vim的简单使用
Linux入门3——vim的简单使用
59 1
|
2月前
|
Linux Shell Windows
Linux入门1——初识Linux指令
Linux入门1——初识Linux指令
33 0
Linux入门1——初识Linux指令
|
2月前
|
存储 数据可视化 Linux
Linux 基础入门
Linux 基础入门
|
2月前
|
Linux Go 数据安全/隐私保护
Linux入门2——初识Linux权限
Linux入门2——初识Linux权限
30 0
|
27天前
|
Linux 网络安全 数据安全/隐私保护
Linux 超级强大的十六进制 dump 工具:XXD 命令,我教你应该如何使用!
在 Linux 系统中,xxd 命令是一个强大的十六进制 dump 工具,可以将文件或数据以十六进制和 ASCII 字符形式显示,帮助用户深入了解和分析数据。本文详细介绍了 xxd 命令的基本用法、高级功能及实际应用案例,包括查看文件内容、指定输出格式、写入文件、数据比较、数据提取、数据转换和数据加密解密等。通过掌握这些技巧,用户可以更高效地处理各种数据问题。
69 8
|
27天前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
180 6
|
28天前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
71 3
|
28天前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
65 2
|
10天前
|
Linux Shell
Linux 10 个“who”命令示例
Linux 10 个“who”命令示例
37 14
Linux 10 个“who”命令示例

热门文章

最新文章