USB 设备 id table 理解

Usb device id table understanding

我试图了解 linux 内核初始化结构的不同方式。在此查询中,我编写了一个示例 usb 驱动程序,但我不理解某些要点,指出了 ??

之前的注释
static struct usb_device_id pen_table[] =  //?? why pen_table is an array
{
    { USB_DEVICE(0xaaaa , 0x8816) },       //??what type of array initialization is this
    {} /* Terminating entry */             //??how this terminates
};

我尝试以这种方式初始化设备 ID table,但在接近初始化时出现错误

static struct  usb_device_id pen_table = {
    .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
    .idVendor=0xaaaa,
    .idProduct = 0x8816,
};

您应该手头有 Linux 内核源代码才能真正理解这一点。

  • 为什么pen_table是数组?

MODULE_DEVICE_TABLE 中有必要(参见 Hard time in understanding MODULE_DEVICE_TABLE(usb, id_table) usage) and in defining instance of usb_driver struct, see http://opensourceforu.efytimes.com/2011/11/usb-drivers-in-linux-2/

  • 这是什么类型的数组初始化?

USB_DEVICE是在include/linux/usb.h:

中定义的宏
#define USB_DEVICE(vend, prod) \
    .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
    .idVendor = (vend), \
    .idProduct = (prod)
  • 这是如何终止的?

C 标准说:

The initialization shall occur in initializer list order, each initializer provided for a particular subobject overriding any previously listed initializer for the same subobject; all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.

和:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:

  • if it has pointer type, it is initialized to a null pointer;
  • if it has arithmetic type, it is initialized to (positive or unsigned) zero;
  • if it is an aggregate, every member is initialized (recursively) according to these rules;
  • if it is a union, the first named member is initialized (recursively) according to these rules.

因此,id_table 被定义为指针而不是 usb_driver 中的数组:

const struct usb_device_id *id_table;

使用 id_table 的函数将递增指向 id_table 的指针,而不是单独传递数组大小,直到其中一个元素为 NULL。请参阅代表此技术的这个简短示例:

#include <stdio.h>
#include <stdlib.h>

struct small
{
    int a;
    int b;
};

struct big
{
    struct small *s;
};

struct small table[] =
    {
        {1, 1},
        {2, 2},
        {3, 3},
        {}
    };

int main(void)
{
    struct big b = {
        .s = table
    };

    const struct small *s;
        /* traverse through table using pointer arithmetic */
    for (s = b.s; s->a; s++)
        {
            printf("%d\n", s->a);
            printf("%d\n", s->b);
        }

    exit(0);
}
  • 我尝试以这种方式初始化设备 ID table,但是我得到了 接近初始化的错误

我不知道,你确定你不是要重新定义 pen_table?什么是错误消息?

它是一个数组,因为它是数据结构的定义和使用方式。

您有 n 个条目,然后是终止条目(在本例中为全零)。

无论在什么地方使用此数组进行初始化,它都会从 table 符号开始并消耗条目,直到它到达终止符,然后停止。这样您也不需要传达条目数。

此模式有助于将配置数据与库进行后期绑定,并允许更多的编译时配置,而不是 运行 时间配置,并且还需要更少的同步才能正确运行(因此机会更少错误)。

你的第二个结构没有终止符,所以解析 table 的东西会一直继续下去,直到它崩溃或出错。