buses初始化
static struct kset *bus_kset;
int __init buses_init(void)
{
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
if (!bus_kset)
return -ENOMEM;
return 0;
}
buses_init调用顺序为:start_kernel->rest_init->kernel_init->do_basic_setup->driver_init->buses_init;该函数完成以下功能
1.动态创建一个kset
2.在sysfs创建一个bus目录
3.向用户空间发送一个KOBJ_ADD事件
注册新bus
/**
* bus_register - register a bus with the system.
* @bus: bus.
*
* Once we have that, we registered the bus with the kobject
* infrastructure, then register the children subsystems it has:
* the devices and drivers that belong to the bus.
*/
int bus_register(struct bus_type *bus)
{
int retval;
struct subsys_private *priv;
// 创建subsys_private结构
priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
// subsys_private结构所属bus_type
priv->bus = bus;
bus->p = priv;
// bus_notifier初始化
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
// 设置bus->p->subsys.kobj.name
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
if (retval)
goto out;
priv->subsys.kobj.kset = bus_kset;
priv->subsys.kobj.ktype = &bus_ktype;
priv->drivers_autoprobe = 1;
// 在/sys/bus/*创建bus的kset目录
retval = kset_register(&priv->subsys);
if (retval)
goto out;
// 在/sys/bus/*/*创建属性文件
retval = bus_create_file(bus, &bus_attr_uevent);
if (retval)
goto bus_uevent_fail;
// 在/sys/bus/*/*创建devices目录
priv->devices_kset = kset_create_and_add("devices", NULL,
&priv->subsys.kobj);
if (!priv->devices_kset) {
retval = -ENOMEM;
goto bus_devices_fail;
}
// 在/sys/bus/*/*创建drivers目录
priv->drivers_kset = kset_create_and_add("drivers", NULL,
&priv->subsys.kobj);
if (!priv->drivers_kset) {
retval = -ENOMEM;
goto bus_drivers_fail;
}
// 初始化设备和驱动链表
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&priv->klist_drivers, NULL, NULL);
// 创建属性文件
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);
out:
kfree(bus->p);
bus->p = NULL;
return retval;
}
EXPORT_SYMBOL_GPL(bus_register);
功能:
1.在/sys/bus下面创建总线目录,如/sys/bus/pci
2.在/sys/bus/总线名/目录创建devices,drivers目录,如:/sys/bus/pci/devices,/sys/bus/pci/drivers
3.创建属性文件
注册pci总线后的kobject和目录结构图大致如下:
下一篇接着分析总线添加设备