为什么Linux设备驱动程序中除了init之外还需要probe方法?

发布于 2024-10-18 21:10:18 字数 148 浏览 5 评论 0原文

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

In the linux kernel, what does the probe() method, that the driver provides, do? How different is it from the driver's init function, i.e. why can't the probe() functions actions be performed in the driver's init function ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

瞄了个咪的 2024-10-25 21:10:18

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

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

更简短的答案,假设 PCI:驱动程序的 init 函数调用 pci_register_driver(),它为内核提供了它能够服务的设备列表,以及指向 >probe() 函数。然后,内核为每个设备调用一次驱动程序的 probe() 函数。

此探测函数启动每个设备的初始化:初始化硬件、分配资源以及向内核注册设备作为块或网络设备或其他设备。

这使得设备驱动程序变得更容易,因为他们永远不需要搜索设备或担心找到热插拔的设备。内核会处理该部分,并在有设备可供您处理时通知正确的驱动程序。

Different device types can have probe() functions. For example, PCI and USB devices both have probe() functions.

If you're talking about PCI devices, I would recommend you read chapter 12 of Linux Device Drivers, which covers this part of driver initialization. USB is covered in chapter 13.

Shorter answer, assuming PCI: The driver's init function calls pci_register_driver() which gives the kernel a list of devices it is able to service, along with a pointer to the probe() function. The kernel then calls the driver's probe() function once for each device.

This probe function starts the per-device initialization: initializing hardware, allocating resources, and registering the device with the kernel as a block or network device or whatever it is.

That makes it easier for device drivers, because they never need to search for devices or worry about finding a device that was hot-plugged. The kernel handles that part and notifies the right driver when it has a device for you to handle.

一个人的夜不怕黑 2024-10-25 21:10:18

@Bandicoot :将调用probe()来确保设备存在并且功能良好。如果设备不可热插拔,则可以将probe()的功能放在init()方法中这将减少驱动程序运行时的内存占用。 PS link

Probe() 在设备启动时发生,或者当设备连接时。对于“平台”设备,当注册平台设备并且其设备名称与设备驱动程序上指定的名称匹配时,将调用探测函数。 PS 链接

i2c_detect函数探测I2C适配器,寻找不同的地址在addr_data结构中指定。如果找到设备,则调用 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 P.S 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- electronics.com/doc/kernel-architecture.pdf

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

在用于内核的 PCI 中- 2.4.29,当供应商和设备 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;
}

@Bandicoot : probe() will be called to make sure that the device exist and the functionality is fine.If device is not hot-pluggable, functionality of probe() can be put inside init() method.This will reduce driver's run time memory footprint. P.S link

Probe() happens at the time of device boot or when device is connected.For a "platform" device the probe function is invoked when a platform device is registered and it's device name matches the name specified on the device driver. P.S link

The i2c_detect function probes the I2C adapter, looking for the different addresses specified in the addr_data structure. If a device is found, the chip_detect function then is called. P.S link.

One link that will surely clear your doubt. P.S link

In kernel 2.4.29, i can show you that how does probe happen ? Please see below (File name: 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 P.S see below function i2c_add_driver()*/
detach_client:  pcf8583_detach,
command:    pcf8583_command

};

File Name: 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;
}

Few important links:

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

In PCI for kernel-2.4.29, it gets called when vendor and device id are identified. PCI bus driver do this for you. Please see below code:

File Name: 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;
}
情释 2024-10-25 21:10:18

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

Probe(*pdev) // 由内核驱动程序机器根据需要使用来检测和安装实际设备

Init(void) // runs once when the driver/module is invoked and sets things up for the kernel driver machine.

Probe(*pdev) // is used by the kernel driver machine as needed to detect and install actual devices

记忆之渊 2024-10-25 21:10:18

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

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

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

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

  3. probexxx_probe()函数的地址。

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

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

The drivers xxx_init_module() function calls pci_register_driver(struct pci_driver *drv) by passing reference to structure of type pci_driver. struct pci_driver is an important structure all PCI drivers should have, which gets initialized with variables like drivers name, table list of PCI devices the driver can support, callback routines for the PCI core subsystem.

The drivers pci_driver structure has important member fields listed below:

  1. name – Name to the driver which is unique among all PCI drivers in the kernel. It will appear under /sys/bus/pci/drivers.

  2. pci_device_id – A table of device identification data consists type of chips this driver supports.

  3. probe – The address of xxx_probe() function.

  4. remove/suspend/resume/shutdown – address to the function that the PCI core system calls when PCI device is removed/suspended/resumed/shutdown respectively. Generally used by upper layers for power management.

For more information on how the probing of driver executed from PCI core refer Linux Device Driver Init.

撞了怀 2024-10-25 21:10:18

多个设备和热插拔

  1. 您正在运行一个大型服务器,其中有许多 PICe 连接的 GPU 加速器。在某个时刻,您决定为空闲插槽购买更多 GPU。

    如果我们使用 init,那么我们必须 rmmodinsmod 模块。但这需要停止所有连接的 GPU,从而导致停机。

    使用探针,我们只需插入新的 GPU 即可进行重新扫描。

  2. 否则无法实现 PCIe 热插拔:https:// electronics.stackexchange.com/questions/208767/does-pcie-hotplug-actually-work-in-practice

QEMU edu PCI设备示例

QEMU有一个名为edu的教育PCI设备,它可以让我们在调用probe时轻松测试。

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

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

-device edu

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

device_add edu
device_del edu

如果设备在启动时连接:

  • 一旦我们 insmod 模块

    ,就会调用

    probe

  • dmesg包含一行类型:pci 0000:00:04, 就会调用probe : [1234:11e8] ... 这表明我们的设备已被探测到 BDF 0000:00:04

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

    因此我们得出结论,PCI 设备在启动时被探测,并存储在列表中的某个位置。

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

  • 在执行此操作之前不会发生任何事情:

    回声1> /sys/总线/pci/重新扫描
    

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

  • 重新扫描后:

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

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

    • 如果我们没有:probeinsmod 之后立即调用

Multiple devices and hotplug

  1. You are running a large server with many PICe connected GPUs accelerators. At some point you decide to buy more GPUs for the free slots.

    If we used init, then we'd have to rmmod and insmod the module. But that would require stopping all connected GPUs, which causes downtime.

    With probe, we just plug in the new GPUs do a rescan.

  2. PCIe hotplug wouldn't be possible otherwise: https://electronics.stackexchange.com/questions/208767/does-pcie-hotplug-actually-work-in-practice

QEMU edu PCI device example

QEMU has an educational PCI device called edu, which allows us to easily test when probe is called.

First, we need a minimal Linux kernel PCI driver for it, which I've written here.

We can start with the device attached with:

-device edu

but even more interestingly, we can attach and remove the device from the QEMU monitor as well, Ctrl + Alt + 2 on SDL GUI or -monitor telnet::45454,server,nowait on CLI, with the commands:

device_add edu
device_del edu

If the device is attached at boot:

  • probe is called as soon as we insmod the module

  • dmesg contains a line of type: pci 0000:00:04: [1234:11e8] ... that shows that our device was probed to BDF 0000:00:04.

    We know that this is our device, because the vendor is 0x1234 and device id 11e8 in the QEMU source.

    So we conclude that PCI devices are probed at boot, and stored in a list somewhere.

If we attach the device after boot from the monitor:

  • nothing happens until we do:

    echo 1 > /sys/bus/pci/rescan
    

    See also: How can the linux kernel be forced to enumerate the PCI-e bus?

  • after rescan:

    • if we had already insmodded, probe is called immediately.

      So in this case, probe happened separately from insmod, showing how they differ.

    • if we haven't: probe is called immediately after insmod

清晰传感 2024-10-25 21:10:18

Linux 内核使用与软件设备驱动程序进程相匹配的硬件设备init 很早就被调用,并向内核注册 probe 函数和硬件设备名称(如“taiko_sound_card”)。这是为了告诉内核“我是这个名称的设备的软件驱动程序”。当内核遍历硬件设备(设备树或总线枚举)并找到匹配项时,它将调用您注册的 probe 函数。 现在您的软件设备驱动程序拥有硬件设备。

如果没有找到匹配的设备,您的探测器可能永远不会被调用。这就是为什么通常 init 很小并且 probe 完成所有 init 工作的原因。

Linux kernel uses a hardware device matching a software device driver process. init is called very early, and registers probe function and a hardware device name like "taiko_sound_card", to the kernel. This is to tell kernel that "I am sw driver for this device of this name". When the kernel goes through hw devices (device tree or bus enum), and finds a match, it will call your registered probe function. Now your sw device driver owns the hw device.

If no matching device is found, your probe may never get called. This is why typically init is tiny and probe does all the init work.

甜柠檬 2024-10-25 21:10:18

当结构内的函数指针调用probe()方法时,探测就完成了,该结构用于与设备相关的默认或自定义平台数据进行设备绑定。
驱动程序使用大量有关设备的信息,以便当 id_table 名称字段中的条目与设备名称匹配时,探测会向驱动程序提供此类信息。

Probing is done when the probe() method is called by function pointer inside a structure which is used to device binding with default or custom platform data regarding to device.
drivers uses lots of information about device so that the probing provides such information to drivers when an entry in the id_table name field matches device name will be probe.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文