通过bus_register()函数可以弄清楚整个设备模型的骨架。大致的架构弄清楚之后就可以继续填充这个模型了。根据总线、设备、驱动由高层到底层的顺序,可以以设备为入口点来继续探索。
设备的入口在device_register()函数当中。该函数相当简单,仅包含两个函数调用,第一个是device_initialize(),第二个是device_add()函数。根据调用顺序依次阅读其源码。抛开与设备模型无关的代码不谈,虽然sysfs也属于设备模型,但可以忽略它。没有显示的说明,所列出的代码都来自
drivers/base/core.c文件。
首先第一个函数device_initialize()。
570 dev->kobj.kset = devices_kset;
由此可见,所有的设备都在这个名叫devices_kset的容器当中,可以称其为设备容器。
571 kobject_init(&dev->kobj, &device_ktype);
显然,所有的设备都属于device_ktype类型的。
在设备模型当中,该函数的作用就是将该设备放入设备容器当中,并设置设备类型。
第二个函数device_add()。
971 parent = get_device(dev->parent);
972 setup_parent(dev, parent);
这两条语句设置该设备的内嵌kobject的父kobject为其父设备的kobject。当然,该设备可能没有父设备。再次体现出kobject在设备模型中对理清各个设备层次关系的重要性。
980 error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
将该设备添加到上层设备的内嵌kobject链表当中。即dev->kobj.parent.list链表。dev->kobj.parent可能为空,由kobject_add函数可知,会将dev->kobj.kset.kobj设置为dev->kobj.parent。
而dev->kobj.kset就是devices_kset。这样对于没有父设备的设备就直接在devices_kset的下层。而devices_kset只是一个容器.所以该设备就属于顶层设备。
1010 error = bus_add_device(dev);
这里在设备层次上暴露出与总线的交互关系.跟踪其函数调用。只有一条语句与设备模型相关。
在drivers/base/bus.c文件当中:
467 klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
该语句就是将该设备添加到其所连接到的总线上设备链表当中。由此可知,通过总线的设备链表可以获知所有连接到该总线的设备。相当明了了... (有兴趣的童鞋可以浏览一下klist的接口)
1026 bus_probe_device(dev);
设备在驱动模型自设备往上的逻辑结构已经完成了.现在就该给device找个能够驱动它的驱动了。不在此做延伸.这里涉及到了总线、设备、驱动三者之间的关系.而这里仅以设备位主线来考察。留待驱动这个层次分析清楚之后再作展开。
1027 if (parent)
1028 klist_add_tail(&dev->p->knode_parent,
1029 &parent->p->klist_children);
如果该设备有父设备.就将其添加到父设备的子设备链表当中。
以上就是device_register所做的所有事情.其中主要就是理清该设备在设备模型中与总线、父设备以及驱动之间的所有复杂的关系.
阅读(1973) | 评论(0) | 转发(0) |