为什么Linux设备驱动程序中除了初始化之外还需要探测方法?

在linux内核中,驱动程序提供的probe()方法是做什么的? 与驱动程序的init函数有什么不同,也就是说为什么不能在驱动程序的init函数中执行probe()函数的动作?

不同的设备types可以有probe()函数。 例如,PCI和USB设备都具有probe()function。

如果您正在讨论PCI设备,我build议您阅读Linux设备驱动程序的第12章,其中涵盖了驱动程序初始化的这一部分。 USB在第13章中介绍。

较短的答案,假设PCI:驱动程序的初始化函数调用pci_register_driver() ,它给内核一个能够服务的设备列表,以及指向probe()函数的指针。 然后内核为每个设备调用驱动程序的probe()函数一次。

这个探测function启动每个设备的初始化:初始化硬件,分配资源,以及将设备作为块或networking设备注册到内核,或者不pipe它是什么。

这使设备驱动程序更容易,因为它们不需要search设备或担心find热插拔的设备。 内核处理这个部分,并在它有一个处理设备的时候通知正确的驱动程序。

Init(void)//在调用驱动程序/模块时运行一次,并为内核驱动程序机器设置内容。

Probe(* pdev)//被内核驱动程序机器用来检测和安装实际的设备

@android :probe()将被调用,以确保设备的存在和function是好的。如果设备不可热插拔,probe()的function可以放在init()方法内。这将减less驱动程序的运行时间内存占用。 PS 链接

Probe()在设备引导时或设备连接时发生。对于“平台”设备,在平台设备注册时调用探测function,设备名称与设备驱动程序中指定的名称相匹配。 PS 链接

i2c_detect函数探测I2C适配器,查找在addr_data结构中指定的不同地址。 如果find设备,则调用chip_detect函数。 PS 链接 。

一个肯定会清除你的疑问的链接。 PS 链接

在内核2.4.29中,我可以告诉你如何探测发生? 请看下面(文件名: drivers / acorn / char / pcf8583.c

 static struct i2c_driver pcf8583_driver = { name: "PCF8583", id: I2C_DRIVERID_PCF8583, flags: I2C_DF_NOTIFY, attach_adapter: pcf8583_probe, /* This will be called from i2c-core.c PS see below function i2c_add_driver()*/ detach_client: pcf8583_detach, command: pcf8583_command 

};

文件名: drivers / i2c / i2c-core.c

 int i2c_add_driver(struct i2c_driver *driver) { ........................ ........................ /* now look for instances of driver on our adapters */ if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) { for (i=0;i<I2C_ADAP_MAX;i++) if (adapters[i]!=NULL) /* Ignore errors */ driver->attach_adapter(adapters[i]); /*This is a location from where probe is called. Pointer **driver** is of type **pcf8583_driver** which you have passed into this function*/ } ADAP_UNLOCK(); return 0; } 

几个重要的环节:

1) http://www.slideshare.net/varunmahajan06/i2c-subsystem-in-linux2624

2) http://www.programering.com/a/MjNwcTMwATM.html

3) http://www.linuxjournal.com/article/6717

4) http://www.developermemo.com/2943157/

5) http://free-electrons.com/doc/kernel-architecture.pdf

6) http://www.techques.com/question/1-3014627/Probe-problem-when-writing-a-I2C-device-driver

在kernel-2.4.29的PCI中,当供应商和设备ID被标识时,它被调用。 PCI总线驱动程序为你做这个。 请看下面的代码:

文件名: drivers / pci / pci.c

 static int pci_announce_device(struct pci_driver *drv, struct pci_dev *dev) { const struct pci_device_id *id; int ret = 0; if (drv->id_table) { id = pci_match_device(drv->id_table, dev); /* check for device presence*/ if (!id) { ret = 0; goto out; } } else id = NULL; dev_probe_lock(); if (drv->probe(dev, id) >= 0) { /* This is a location from where probe is called*/ dev->driver = drv; ret = 1; } dev_probe_unlock(); out: return ret; } 

驱动程序xxx_init_module()函数通过传递对pci_drivertypes的结构的引用来调用pci_register_driver(struct pci_driver *drv)struct pci_driver是所有PCI驱动程序应该具有的重要结构,它使用诸如驱动程序名称,驱动程序可以支持的PCI设备的表列表,以及PCI核心子系统的callback例程等variables进行初始化。

驱动程序pci_driver结构具有下列重要的成员字段:

  1. name – 内核中所有PCI驱动程序中唯一的驱动程序名称。 它会出现在/sys/bus/pci/drivers

  2. pci_device_id – 设备标识数据表包含此驱动程序支持的芯片types。

  3. probexxx_probe()函数的地址。

  4. 当PCI设备分别被移除/挂起/恢复/closures时, remove/suspend/resume/shutdown – PCI核心系统调用的function的地址。 通常由上层用于电源pipe理。

有关如何从PCI内核执行驱动程序的探测的更多信息,请参阅Linux设备驱动程序初始化 。

当一个结构中的函数指针调用probe()方法时,探测完成,该结构用于设备与关于设备的默认或定制平台数据进行绑定。 驱动程序使用大量关于设备的信息,以便在id_table名称字段中的条目与设备名称相匹配时,探测将这些信息提供给驱动程序。

多个设备和热插拔

  1. 您正在运行一个具有多个PICe连接的GPU加速器的大型服务器。 在某些时候,您决定为免费插槽购买更多的GPU。

    如果我们使用init ,那么我们不得不rmmodinsmod模块。 但是这需要停止所有连接的GPU,这会导致停机。

    使用probe ,我们只需插入新的GPU即可重新扫描。

  2. 否则PCIe热插拔将不可能: https : //electronics.stackexchange.com/questions/208767/does-pcie-hotplug-actually-work-in-practice

QEMU edu PCI设备示例

QEMU有一个名为edu的教育PCI设备,可以让我们轻松testing何时调用probe

首先,我们需要一个最小的Linux内核PCI驱动程序。

我们可以从附带的设备开始:

 -device edu 

但更有意思的是,我们可以在QEMU监视器上附加和删除设备,在SDL GUI上使用Ctrl + Alt + 2或在CLI上使用-monitor telnet::45454,server,nowait ,命令如下:

 device_add edu device_del edu 

如果设备在启动时连接:

  • probe一旦我们insmod模块就会被调用

  • dmesg包含一行: pci 0000:00:04: [1234:11e8] ...表明我们的设备被探测到BDF 0000:00:04

    我们知道这是我们的设备,因为QEMU源中的供应商是0x1234和设备ID 11e8。

    所以我们得出这样的结论:PCI设备在启动时被探测,并存储在某个列表中。

如果我们从显示器启动后连接设备:

  • 直到我们做下去,

     echo 1 > /sys/bus/pci/rescan 

    另请参见: 如何强制Linux内核枚举PCI-e总线?

  • 重新扫描后:

    • 如果我们已经安装好了,立即调用probe

      所以在这种情况下, probeinsmod分开发生,显示它们的不同之处。

    • 如果我们没有:在insmod之后立即调用probe