devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
模型如下
然后是platform的注册
在platform的注册中,分为两个部分,一部分是注册到devices中,另一部分是注册到bus中,代码在/drivers/base/platform.c中
int __init platform_bus_init(void)
{
int error;
//注册到devices目录中
error = device_register(&platform_bus);
if (error)
return error;
//注册到bus目录中
error = bus_register(&platform_bus_type);
if (error)
device_unregister(&platform_bus);
return error;
}
首先是device_register,注册的参数为platform_bus,如下所示
struct device platform_bus = {
.bus_id = "platform",
};
很简单,只有一个参数,表明了目录名
int device_register(struct device *dev)
{
//初始化dev结构
device_initialize(dev);
//添加dev至目录
return device_add(dev);
}
void device_initialize(struct device *dev)
{
//重要的一步,指明了父容器为devices_kset,而devices_kset的注册在前面已经介绍过了
dev->kobj.kset = devices_kset;
//初始化kobj的ktype为device_ktype
kobject_init(&dev->kobj, &device_ktype);
klist_init(&dev->klist_children, klist_children_get,
klist_children_put);
INIT_LIST_HEAD(&dev->dma_pools);
INIT_LIST_HEAD(&dev->node);
init_MUTEX(&dev->sem);
spin_lock_init(&dev->devres_lock);
INIT_LIST_HEAD(&dev->devres_head);
device_init_wakeup(dev, 0);
set_dev_node(dev, -1);
}
int device_add(struct device *dev)
{
struct device *parent = NULL;
struct class_interface *class_intf;
int error;
dev = get_device(dev);
if (!dev || !strlen(dev->bus_id)) {
error = -EINVAL;
goto Done;
}
pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
parent = get_device(dev->parent);
setup_parent(dev, parent);
if (parent)
set_dev_node(dev, dev_to_node(parent));
//设置dev->kobj的名字和父对象,并建立相应的目录
error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);
if (error)
goto Error;
if (platform_notify)
platform_notify(dev);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_ADD_DEVICE, dev);
//建立uevent文件
error = device_create_file(dev, &uevent_attr);
if (error)
goto attrError;
if (MAJOR(dev->devt)) {
error = device_create_file(dev, &devt_attr);
if (error)
goto ueventattrError;
}
//建立subsystem连接文件连接到所属class,这里没有设置class对象所以不会建立
error = device_add_class_symlinks(dev);
if (error)
goto SymlinkError;
//建立dev的描述文件,这里没有设置描述文件所以不会建立
error = device_add_attrs(dev);
if (error)
goto AttrsError;
//建立链接文件至所属bus,这里没有设置所属bus所以不会建立
error = bus_add_device(dev);
if (error)
goto BusError;
//添加power文件,因为platform不属于设备,所以不会建立power文件
error = device_pm_add(dev);
if (error)
goto PMError;
kobject_uevent(&dev->kobj, KOBJ_ADD);
//检测驱动中有无适合的设备进行匹配,但没有设置bus,所以不会进行匹配
bus_attach_device(dev);
if (parent)
klist_add_tail(&dev->knode_parent, &parent->klist_children);
if (dev->class) {
down(&dev->class->sem);
list_add_tail(&dev->node, &dev->class->devices);
list_for_each_entry(class_intf, &dev->class->interfaces, node)
if (class_intf->add_dev)
class_intf->add_dev(dev, class_intf);
up(&dev->class->sem);
}
Done:
put_device(dev);
return error;
PMError:
bus_remove_device(dev);
BusError:
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_DEL_DEVICE, dev);
device_remove_attrs(dev);
AttrsError:
device_remove_class_symlinks(dev);
SymlinkError:
if (MAJOR(dev->devt))
device_remove_file(dev, &devt_attr);
ueventattrError:
device_remove_file(dev, &uevent_attr);
attrError:
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
Error:
cleanup_device_parent(dev);
if (parent)
put_device(parent);
goto Done;
}
在kobject_add-> kobject_add_varg-> kobject_add_internal中
//提取父对象,因为没有设置,所以为空
parent = kobject_get(kobj->parent);
//父容器存在则设置父对象,在前面的dev->kobj.kset = devices_kset中设为了devices_kset
if (kobj->kset) {
//检测是否已经设置父对象
if (!parent)
//无则使用父容器为父对象
parent = kobject_get(&kobj->kset->kobj);
//添加该kobj到父容器的链表中
kobj_kset_join(kobj);
//设置父对象
kobj->parent = parent;
}
现在devices下的platform目录建立好了,模型如下,其中红线描绘了目录关系
现在到bus_register了
注册的参数platform_bus_type如下所示
struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.suspend = platform_suspend,
.suspend_late = platform_suspend_late,
.resume_early = platform_resume_early,
.resume = platform_resume,
};
int bus_register(struct bus_type *bus)
{
int retval;
//声明一个总线私有数据并分配空间
struct bus_type_private *priv;
priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
//互相关联
priv->bus = bus;
bus->p = priv;
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
//设置私有数据中kobj对象的名字
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
if (retval)
goto out;
//设置父容器为bus_kset,操作集为bus_ktype
priv->subsys.kobj.kset = bus_kset;
priv->subsys.kobj.ktype = &bus_ktype;
priv->drivers_autoprobe = 1;
//注册bus容器
retval = kset_register(&priv->subsys);
if (retval)
goto out;
//建立uevent属性文件
retval = bus_create_file(bus, &bus_attr_uevent);
if (retval)
goto bus_uevent_fail;
//建立devices目录
priv->devices_kset = kset_create_and_add("devices", NULL,
&priv->subsys.kobj);
if (!priv->devices_kset) {
retval = -ENOMEM;
goto bus_devices_fail;
}
//建立drivers目录
priv->drivers_kset = kset_create_and_add("drivers", NULL,
&priv->subsys.kobj);
if (!priv->drivers_kset) {
retval = -ENOMEM;
goto bus_drivers_fail;
}
//初始化klist_devices和klist_drivers链表
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&priv->klist_drivers, NULL, NULL);
//增加probe属性文件
retval = add_probe_files(bus);
if (retval)
goto bus_probe_files_fail;
//增加总线的属性文件
retval = bus_add_attrs(bus);
if (retval)
goto bus_attrs_fail;
pr_debug("bus: '%s': registered\n", bus->name);
return 0;
bus_attrs_fail:
remove_probe_files(bus);
bus_probe_files_fail:
kset_unregister(bus->p->drivers_kset);
bus_drivers_fail:
kset_unregister(bus->p->devices_kset);
bus_devices_fail:
bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail:
kset_unregister(&bus->p->subsys);
kfree(bus->p);
out:
return retval;
}
在kset_register-> kobject_add_internal中
//提取父对象,因为没有设置父对象,所以为空
parent = kobject_get(kobj->parent);
//父容器存在则设置父对象,在上文中设置了父容器priv->subsys.kobj.kset = bus_kset
if (kobj->kset) {
//检测是否已经设置父对象
if (!parent)
//无则使用父容器为父对象
parent = kobject_get(&kobj->kset->kobj);
//添加该kobj到父容器的链表中
kobj_kset_join(kobj);
//设置父对象
kobj->parent = parent;
}
在retval = kset_register(&priv->subsys)完成之后platform在bus下的模型如下图
有印象的话大家还记得在platform下面有两个目录devices和drivers吧~
现在就到这两个目录的注册了
priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);
注意这两条语句的头部
priv->devices_kset = kset_create_and_add
priv->drivers_kset = kset_create_and_add
可以清楚的看到bus_type_private下的devices_kset, drivers_kset分别连接到了devices,drivers的kset上
现在来看kset_create_and_add("devices", NULL,&priv->subsys.kobj);
struct kset *kset_create_and_add(const char *name,
struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
//参数为"devices", NULL,&priv->subsys.kobj
{
struct kset *kset;
int error;
//创建一个kset容器
kset = kset_create(name, uevent_ops, parent_kobj);
if (!kset)
return NULL;
//注册创建的kset容器
error = kset_register(kset);
if (error) {
kfree(kset);
return NULL;
}
return kset;
}
在kset_create 中比较重要的操作为
kset->kobj.ktype = &kset_ktype //设置了ktype,为kset_ktype
kset->kobj.parent = parent_kobj; //设置了父对象,为priv->subsys.kobj,也就是platform_bus_type->p->subsys.kobj
kset->kobj.kset = NULL; //设置父容器为空
在kset_register中
//提取父对象
parent = kobject_get(kobj->parent); //在之前设置为了
//父容器存在则设置父对象,由于父容器为空,不执行以下代码
if (kobj->kset) {
//检测是否已经设置父对象
if (!parent)
//无则使用父容器为父对象
parent = kobject_get(&kobj->kset->kobj);
//添加该kobj到父容器的链表中
kobj_kset_join(kobj);
//设置父对象
kobj->parent = parent;
}
至此, devices的模型就建立好了,drivers模型的建立和devices是一致的,只是名字不同而已,我就不复述了,