我试图了解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表,但是我在接近初始化时遇到错误
static struct usb_device_id pen_table = {
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor=0xaaaa,
.idProduct = 0x8816,
};
答案 0 :(得分:2)
你应该有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);
}
我不确定,您确定不会尝试重新定义pen_table
吗?什么是错误信息?
答案 1 :(得分:0)
它是一个数组,因为它是如何定义和使用数据结构的。
您有n个条目,然后是终止条目(在这种情况下,全部为零)。
无论在初始化中使用此数组,它都将从表符号开始并消耗条目,直到它到达终结符,然后停止。这样您也不需要传达条目数。
此模式有助于配置数据与库的后期绑定,并允许更多的编译时配置,而不是运行时配置,并且还需要更少的事情来同步才能正常运行(因此错误的机会更少)。
你的第二个结构没有终结器,所以解析表的东西一直在继续,直到它崩溃或出错。