【问题标题】:Usb device id table understandingusb设备id表理解
【发布时间】:2015-10-29 11:54:19
【问题描述】:

我试图了解 linux 内核初始化结构的不同方式。在这个查询中,我编写了一个示例 USB 驱动程序,但我不明白一些点,指出为 cmets 前面??

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 表,但在初始化时出现错误

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

【问题讨论】:

    标签: c linux usb drivers


    【解决方案1】:

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

    • 为什么pen_table 是一个数组?

    MODULE_DEVICE_TABLE(参见Hard time in understanding MODULE_DEVICE_TABLE(usb, id_table) usage)和定义usb_driver结构的实例时,它是必需的,参见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 标准说:

    初始化应按初始化列表顺序进行,每个 为覆盖任何特定子对象提供的初始化程序 先前列出的相同子对象的初始化程序;所有子对象 未显式初始化的将被隐式初始化 与具有静态存储持续时间的对象相同。

    和:

    如果具有自动存储持续时间的对象未初始化 明确地说,它的值是不确定的。如果一个物体有静电 存储时长未显式初始化,则:

    • 如果有指针类型,则初始化为空指针;
    • 如果它具有算术类型,则初始化为(正数或 无符号)零;
    • 如果是聚合,每个成员都被初始化(递归) 根据这些规则;
    • 如果是联合,则初始化第一个命名成员 (递归地)根据这些规则。

    因此,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 表,但我得到了 接近初始化的错误

    我没有,你确定你不是要重新定义pen_table吗?什么是错误信息?

    【讨论】:

    • 你的例子很好,但你不应该在不同上下文的三个地方使用's'。
    • 唯一可以使用不同标识符的地方是const struct small *s,例如可以是const struct small *sp;for循环可以是for (sp = b.s; sp-&gt;a; sp++) { printf("%d\n", sp-&gt;a); printf("%d\n", sp-&gt;b); }
    【解决方案2】:

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

    您有 n 个条目,然后是一个终止条目(在这种情况下,全为零)。

    无论这个数组在哪里初始化,它都会从表符号开始并消耗条目,直到它到达终止符,然后停止。这样,您也不需要传达条目的数量。

    这种模式有助于将配置数据与库进行后期绑定,并允许更多的编译时配置,而不是运行时配置,并且需要更少的东西来同步以正确操作(因此出错的机会更少)。

    您的第二个结构没有终止符,因此解析表的东西只会继续运行,直到崩溃或出错。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-06
      相关资源
      最近更新 更多