本文中的结构信息基于Kernel5.10.160,不过本文讨论内容适用于目前为止的所有内核:
struct platform_driver
定义
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
bool prevent_deferred_probe;
ANDROID_KABI_RESERVE(1);
};
struct device_driver
定义
struct device_driver {
const char *name;
struct bus_type *bus;
struct module *owner;
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
enum probe_type probe_type;
const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;
int (*probe) (struct device *dev);
void (*sync_state)(struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;
const struct attribute_group **dev_groups;
const struct dev_pm_ops *pm;
void (*coredump) (struct device *dev);
struct driver_private *p;
ANDROID_KABI_RESERVE(1);
ANDROID_KABI_RESERVE(2);
ANDROID_KABI_RESERVE(3);
ANDROID_KABI_RESERVE(4);
};
可以看出上面的两个结构中都有probe
、remove
等函数,但是翻看platform驱动会发现,没有二般的大家一般都把probe和remove函数注册到了platform上,这是为什么呢?
示例代码如下:
static struct platform_driver rk_gmac_dwmac_driver = {
.probe = rk_gmac_probe,
.remove = rk_gmac_remove,
.driver = {
.name = "rk_gmac-dwmac",
.pm = &rk_gmac_pm_ops,
.of_match_table = rk_gmac_dwmac_match,
},
};
module_platform_driver(rk_gmac_dwmac_driver);
struct platform_driver
和struct device_driver
中的probe
和remove
函数在功能上是相似的,但它们的应用场景和具体实现有所不同:
-
struct platform_driver:
- probe:
- 类型:
int (*probe)(struct platform_device *pdev)
- 作用:当平台设备与驱动程序匹配时调用。用于初始化设备,分配资源,注册中断处理程序等。
- 类型:
- remove:
- 类型:
int (*remove)(struct platform_device *pdev)
- 作用:当设备被移除或驱动程序被卸载时调用。用于释放资源,注销中断处理程序等。
- 类型:
- probe:
-
struct device_driver:
- probe:
- 类型:
int (*probe)(struct device *dev)
- 作用:当设备与驱动程序匹配时调用。与
platform_driver
中的probe
类似,但更通用,适用于所有类型的设备,而不仅仅是平台设备。
- 类型:
- remove:
- 类型:
int (*remove)(struct device *dev)
- 作用:当设备被移除或驱动程序被卸载时调用。与
platform_driver
中的remove
类似,但更通用,适用于所有类型的设备。
- 类型:
- probe:
区别总结
- 应用场景:
platform_driver
专用于平台设备,而device_driver
是更通用的驱动程序接口,适用于所有类型的设备。 - 参数类型:
platform_driver
中的probe
和remove
函数接受struct platform_device *
类型的参数,而device_driver
中的probe
和remove
函数接受struct device *
类型的参数。
通常情况下,如果你在开发平台设备驱动程序,会使用struct platform_driver
中的probe
和remove
函数。如果你在开发更通用的驱动程序,可能会使用struct device_driver
中的probe
和remove
函数。
那是否可以不注册struct platform_driver中的probe和remove,而直接注册drvier中的呢
在开发平台设备驱动程序时,通常会使用struct platform_driver
中的probe
和remove
函数,因为它们专门为平台设备设计,参数类型和调用机制都与平台设备匹配。
虽然理论上你可以只注册struct device_driver
中的probe
和remove
函数,但这样做并不推荐,原因如下:
-
平台设备特定性:
struct platform_driver
中的probe
和remove
函数接受struct platform_device *
类型的参数,这使得它们更适合处理平台设备的特定需求。- 使用
struct device_driver
中的probe
和remove
函数会使代码更复杂,因为你需要在函数内部进行类型转换和额外的检查。
-
代码清晰性和维护性:
- 使用
struct platform_driver
可以使代码更清晰,易于理解和维护。它明确表明这是一个平台设备驱动程序。 - 直接使用
struct device_driver
可能会导致混淆,特别是在团队合作或代码审查时。
- 使用
-
内核框架一致性:
- Linux内核框架为不同类型的设备提供了专门的驱动程序结构体,如
platform_driver
、pci_driver
等。遵循这些框架有助于保持代码的一致性和可维护性。
- Linux内核框架为不同类型的设备提供了专门的驱动程序结构体,如
因此,建议在开发平台设备驱动程序时,使用struct platform_driver
中的probe
和remove
函数。