为什么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_driver
types的结构的引用来调用pci_register_driver(struct pci_driver *drv)
。 struct pci_driver
是所有PCI驱动程序应该具有的重要结构,它使用诸如驱动程序名称,驱动程序可以支持的PCI设备的表列表,以及PCI核心子系统的callback例程等variables进行初始化。
驱动程序pci_driver结构具有下列重要的成员字段:
-
name
– 内核中所有PCI驱动程序中唯一的驱动程序名称。 它会出现在/sys/bus/pci/drivers
。 -
pci_device_id
– 设备标识数据表包含此驱动程序支持的芯片types。 -
probe
–xxx_probe()
函数的地址。 -
当PCI设备分别被移除/挂起/恢复/closures时,
remove/suspend/resume/shutdown
– PCI核心系统调用的function的地址。 通常由上层用于电源pipe理。
有关如何从PCI内核执行驱动程序的探测的更多信息,请参阅Linux设备驱动程序初始化 。
当一个结构中的函数指针调用probe()方法时,探测完成,该结构用于设备与关于设备的默认或定制平台数据进行绑定。 驱动程序使用大量关于设备的信息,以便在id_table名称字段中的条目与设备名称相匹配时,探测将这些信息提供给驱动程序。
多个设备和热插拔
-
您正在运行一个具有多个PICe连接的GPU加速器的大型服务器。 在某些时候,您决定为免费插槽购买更多的GPU。
如果我们使用
init
,那么我们不得不rmmod
和insmod
模块。 但是这需要停止所有连接的GPU,这会导致停机。使用
probe
,我们只需插入新的GPU即可重新扫描。 -
否则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] ...
表明我们的设备被探测到BDF0000:00:04
。我们知道这是我们的设备,因为QEMU源中的供应商是0x1234和设备ID 11e8。
所以我们得出这样的结论:PCI设备在启动时被探测,并存储在某个列表中。
如果我们从显示器启动后连接设备:
-
直到我们做下去,
echo 1 > /sys/bus/pci/rescan
另请参见: 如何强制Linux内核枚举PCI-e总线?
-
重新扫描后:
-
如果我们已经安装好了,立即调用
probe
。所以在这种情况下,
probe
与insmod
分开发生,显示它们的不同之处。 -
如果我们没有:在
insmod
之后立即调用probe
-