记得有次面试的时候,面试官问我linux设备和驱动具体是如何匹配的。当时没有很详细的回答出来,我们可能就知道是通过设备树中的compatible属性进行匹配,但具体的匹配流程可能不知道。
Linux设备驱动模型中,需要我们关心总线、设备、驱动三个实体,总线将设备和驱动进行绑定,在内核每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动的时候,也会寻找与之匹配的设备,而匹配由总线完成。一般而言,一个现实的Linux设备和驱动需要挂接在一种总线上。根据代码,总结出大致的流程如下:
driver_match_device函数中会调用到bus_type中定义到match函数
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
以平台总线为例:
struct bus_type platform_bus_type = {
.name = "platform",
.dev_groups = platform_dev_groups,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
EXPORT_SYMBOL_GPL(platform_bus_type);
则会调用到platform_match函数:
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 */ /* 匹配设备数中compatible属性 */
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 */ /* 匹配id_table中的name */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;
/* fall-back to driver name match */ /* 最后匹配设备和驱动的name */
return (strcmp(pdev->name, drv->name) == 0);
}
我们可以看到匹配的顺序:
1、先用设备树中的 compatible
属性和 platform_driver
中的driver
中的 of_match_table
来匹配
2、再用 platform_driver
中的 id_table
中的 name
和 platform_device
中的 name
来匹配
3、最后用platform_device
中的name
和 platform_driver
中的 driver
中的 name
来匹配
以上是以平台总线的样例,其他定义总线bus_type匹配的亦如此。