所以 drv->kobj.kset = &bus->drivers;这个做的事情需要结合函数 kobject_register->kobject_add函数中去
static void unlink(struct kobject * kobj)
{
if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem);
list_del_init(&kobj->entry);
up_write(&kobj->kset->subsys->rwsem);
}
kobject_put(kobj);
}
/**
* kobject_add - add an object to the hierarchy.
* @kobj: object.
*/
int kobject_add(struct kobject * kobj)
{
int error = 0;
struct kobject * parent;
if (!(kobj = kobject_get(kobj)))
return -ENOENT;
if (!kobj->k_name)
kobj->k_name = kobj->name;
parent = kobject_get(kobj->parent);
pr_debug("kobject %s: registering. parent: %s, set: %s\n",
kobject_name(kobj), parent ? kobject_name(parent) : "",
kobj->kset ? kobj->kset->kobj.name : "" );
if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem);
if (!parent)
parent = kobject_get(&kobj->kset->kobj);
list_add_tail(&kobj->entry,&kobj->kset->list); //kobj的list_head内容加到bus->drivers的list链表中
up_write(&kobj->kset->subsys->rwsem);
}
kobj->parent = parent;
error = create_dir(kobj);
if (error) {
/* unlink does the kobject_put() for us */
unlink(kobj);
if (parent)
kobject_put(parent);
} else {
kobject_hotplug(kobj, KOBJ_ADD);
}
return error;
}
在这里有这么一个list_add_tail宏来完成device_driver中将成员kobject的kset链表头加入到kobj->kset->list中去,实际是drv->kobj.kset = &bus->drivers,也就是加入到链表头bus->drivers->list中去。这样就顺利完成了在设备注册时,可以遍历到这个链表头下面的驱动。
总结一下的话,其实devices和driver在注册中,最终都会挂接到bus下面,类型是kset(device和driver)下的list。最终都去遍历这个链表头下面对应的驱动和设备。而我们知道一个驱动可以有多个设备,因此device下的driver_list会添加到driver下面的链表头中去。
相对于driver_register的实现,device_register这方面的实现,就简单多了,一句list_add_tail(&dev->bus_list, &dev->bus->devices.list); //将设备的bus_list加入到devoces.list的链表头中,这个简单了很多很多。很明了,而不需要像驱动那样将kobj下面的链表加入到Bus下面去用于遍历。
总之,这个问题很小,但是和内核走的很近很近,所以,遇到这个问题我想必须解决,这样可以带给我对驱动很深入的理解。继续努力,走在linux的世界里。