Linux驱动中,probe函数何时被调用

Linux驱动中,probe函数何时被调用

2023年6月26日发(作者:)

Linux驱动中,probe函数何时被调⽤最近看到linux的设备驱动模型,关于Kobject、Kset等还不是很清淅。看到了struct device_driver这个结构时,想到⼀个问题:它的初始化函数到底在哪⾥调⽤呢?以前搞PCI驱动时⽤pci驱动注册函数就可以调⽤它,搞s3c2410驱动时只要在mach-smdk2410.c中的structplatform_device *smdk2410_devices {}中加⼊设备也会调⽤。但从来就没有想过具体的驱动注册并调⽤probe的过程。于是打开SourceInsight追踪了⼀下:从driver_register看起:int driver_register(struct device_driver * drv){ klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put); init_completion(&drv->unloaded); return bus_add_driver(drv);}klist_init与init_completion没去管它,可能是2.6的这个设备模型要做的⼀些⼯作。直觉告诉我要去bus_add_driver。bus_add_driver中:都是些Kobject 与 klist 、attr等。还是与设备模型有关的。但是其中有⼀句:driver_attach(drv);单听名字就很像:void driver_attach(struct device_driver * drv){ bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);}这个熟悉,遍历总线上的设备并设⽤__driver_attach。在__driver_attach中⼜主要是这样:driver_probe_device(drv, dev);跑到driver_probe_device中去看看:有⼀段很重要:if (drv->bus->match && !drv->bus->match(dev, drv)) goto Done;明显,是调⽤的驱动的总线上的match函数。如果返回1,则可以继续,否则就Done了。继承执⾏的话: if (drv->probe) { ret = drv->probe(dev); if (ret) { dev->driver = NULL; goto ProbeFailed; }只要probe存在则调⽤之。⾄此就完成了probe的调⽤。这个过程链的关键还是在drv->bus->match ,因为其余的地⽅出错的话就是注册失败,⽽只要注册不失败且match返回1,那么就铁定会调⽤驱程的probe了。你可以注册⼀个总线类型和总线,并在match中总是返回 1, 会发现,只要struct device_driver中的bus类型正确时,probe函数总是被调⽤.PCI设备有⾃⼰的总线模型,估计在它的match中就有⼀个判断的条件。static int pci_bus_match(struct device *dev, struct device_driver *drv){ struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_driver *pci_drv = to_pci_driver(drv); const struct pci_device_id *found_id; found_id = pci_match_device(pci_drv, pci_dev); if (found_id) return 1; return 0;}再往下跟踪就知道主要是根据我们熟悉的id_table来的。-------------------------------另解-----------------------------------------------------------------------------------------------从driver_register看起,此处我的这⾥是:int driver_register(struct device_driver * drv){if ((drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)) { printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methodsn", drv->name);}klist_init(&drv->klist_devices, NULL, NULL);return bus_add_driver(drv);}

klist_init不相关,不⽤管他,具体再去看bus_add_driver:int bus_add_driver(struct device_driver *drv){//1.先kobject_set_name(&drv->kobj, "%s", drv->name);//2.再kobject_register(&drv->kobj)//3.然后调⽤了:driver_attach(drv)}int driver_attach(struct device_driver * drv){return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);}真正起作⽤的是__driver_attach:static int __driver_attach(struct device * dev, void * data){...if (!dev->driver) driver_probe_device(drv, dev);...}int driver_probe_device(struct device_driver * drv, struct device * dev){...//1.先是判断bus是否match:if (drv->bus->match && !drv->bus->match(dev, drv)) goto done;//2.再具体执⾏probe:ret = really_probe(dev, drv);...}really_probe才是我们要找的函数:static int really_probe(struct device *dev, struct device_driver *drv){...//1.先是调⽤的驱动所属总线的probe函数:if (dev->bus->probe) { ret = dev->bus->probe(dev); if (ret) goto probe_failed;} else if (drv->probe) {//2.再调⽤你的驱动中的probe函数: ret = drv->probe(dev); if (ret) goto probe_failed;}...}其中,drv->probe(dev),才是真正调⽤你的驱动实现的具体的probe函数。也就是对应此⽂标题所问的,probe函数此时被调⽤。声明:以下主要内容参考⾃:

发布者:admin,转转请注明出处:http://www.yc00.com/web/1687754587a39709.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信