下面为一些辅助函数的实现
[cpp]
intdevice_private_init(structdevice *dev)
{
/*从cache中分配private的空间*/
dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL);
if(!dev->p)
return-ENOMEM;
dev->p->device = dev;/*设置dev private属性的device为自身*/
/*初始化klist_children属性,后面传入的两个参数为
get和put函数的实现,分别为对引用计数的增加和
减少*/
klist_init(&dev->p->klist_children, klist_children_get,
klist_children_put);
return0;
}
[cpp]
staticstructkobject *get_device_parent(structdevice *dev,
structdevice *parent)
{
intretval;
if(dev->class) {/*如果device存在class*/
structkobject *kobj = NULL;
structkobject *parent_kobj;
structkobject *k;
/*
* If we have no parent, we live in "virtual".
* Class-devices with a non class-device as parent, live
* in a "glue" directory to prevent namespace collisions.
*/
if(parent == NULL)/*如果没有父设备,创建一个
'virtual'的kobj,这里可以看出,当没有父设备
时,class设备可以用'virtual'(即非class设备)
作为父节点kobj的树
而非class设备不行
*/
parent_kobj = virtual_device_parent(dev);
elseif(parent->class)/*当父设备也是class设备时,直接返回其kobj*/
return&parent->kobj;
else/*父设备存在,但是不是class设备*/
parent_kobj = &parent->kobj;
/* find our class-directory at the parent and reference it */
spin_lock(&dev->class->p->class_dirs.list_lock);
list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
if(k->parent == parent_kobj) {/*遍历同类中的kobj,找到符合的*/
kobj = kobject_get(k);/*递增其引用计数*/
break;
}
spin_unlock(&dev->class->p->class_dirs.list_lock);
if(kobj)
returnkobj;
/* or create a new class-directory at the parent device */
/*程序运行到这里表示没有在dev->class中找到
k->parent==parent_kobj的kobj,所以创建他*/
k = kobject_create();
if(!k)
returnNULL;
/*初始化创建kobj的kset为dev中class->p->class_dirs*/
k->kset = &dev->class->p->class_dirs;
/*添加kobj到其parent的kobj树中,parent字段设置为parent_kobj*/
retval = kobject_add(k, parent_kobj,"%s", dev->class->name);
if(retval
kobject_put(k);
returnNULL;
}
/* do not emit an uevent for this simple "glue" directory */
returnk;
}
if(parent)/*如果parent存在,返回父设备的kobj*/
return&parent->kobj;
returnNULL;
}
[cpp]
staticstructkobject *virtual_device_parent(structdevice *dev)
{
staticstructkobject *virtual_dir = NULL;
if(!virtual_dir)/*创建名为virtual的kobj加入到设备的集合树中*/
virtual_dir = kobject_create_and_add("virtual",
&devices_kset->kobj);
/*返回创建的kobj*/
returnvirtual_dir;
}
我们看看具体在Linux下的相关目录:
设备与class关联
static int device_add_class_symlinks(struct device *dev)
{
int error;
/*没有class的情况直接返回*/
if (!dev->class)
return 0;
/*在dev->kobj目录下生成一个名为'subsystem'的链接文件,指向其所属的class的sys的目录/sys/class/***,例如,接着上面的例子
*/
error = sysfs_create_link(&dev->kobj,
&dev->class->p->class_subsys.kobj,
"subsystem");
生成下图:
……
}
device关联bus
int bus_add_device(struct device *dev)
{
struct bus_type *bus = bus_get(dev->bus);
int error = 0;
/*如果bus存在,才执行下面部分*/
if (bus) {
pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
/*添加属性文件,该属性文件问bus的属性*/
error = device_add_attrs(bus, dev);
if (error)
goto out_put;
/*在bus的devices目录下生成到dev->kobj的链接,名称为dev->kobj的名称*/
error = sysfs_create_link(&bus->p->devices_kset->kobj,
&dev->kobj, dev_name(dev));
例如,我们看/sys/devices/platform/devices/下的serial8250,为链接到/sys/devices/platform/serial8250
if (error)
goto out_id;
/*dev->kobj目录下subsystem为生成的到bus下相关
目录的链接*/
error = sysfs_create_link(&dev->kobj,
&dev->bus->p->subsys.kobj, "subsystem");