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月前
|
机器学习/深度学习 安全 网络协议
Linux防火墙iptables命令管理入门
本文介绍了关于Linux防火墙iptables命令管理入门的教程,涵盖了iptables的基本概念、语法格式、常用参数、基础查询操作以及链和规则管理等内容。
193 73
|
1月前
|
Unix Linux API
Linux内核许可规则 【ChatGPT】
Linux内核许可规则 【ChatGPT】
|
2月前
|
存储 缓存 Unix
Linux 设备驱动程序(三)(上)
Linux 设备驱动程序(三)
25 3
|
2月前
|
Linux
Linux 设备驱动程序(四)
Linux 设备驱动程序(四)
15 1
|
2月前
|
存储 数据采集 缓存
Linux 设备驱动程序(三)(中)
Linux 设备驱动程序(三)
19 1
|
2月前
|
存储 前端开发 大数据
Linux 设备驱动程序(二)(中)
Linux 设备驱动程序(二)
24 1
|
2月前
|
缓存 安全 Linux
Linux 设备驱动程序(二)(上)
Linux 设备驱动程序(二)
21 1
|
1月前
|
Linux API
Linux里的高精度时间计时器(HPET)驱动 【ChatGPT】
Linux里的高精度时间计时器(HPET)驱动 【ChatGPT】
|
2月前
|
存储 缓存 安全
Linux 设备驱动程序(三)(下)
Linux 设备驱动程序(三)
15 0
|
2月前
|
安全 Linux 程序员
Linux 设备驱动程序(二)(下)
Linux 设备驱动程序(二)
18 0