当前位置: > Linux教程 > linux基础 >

LDM上层建筑之Bus---局部窥探

时间:2016-02-22 13:05来源:linux.it.net.cn 作者:IT

首先看下sys/devices怎么来的?

在初始的启动汇编中会跳到start_kernel---->rest_init---->kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND)---->do_basic_setup(void)---->driver_init(void)---->buses_init();

 

int __init buses_init(void)
{
 bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
 if (!bus_kset)
  return -ENOMEM;
 return 0;
}    

 

/sys/bus  就建立了,bus_uevent_ops做什么目前还不了解,先不管了

 

看下platform这个虚拟的bus怎么建立的。

 

同样是在driver_init(void)---->platform_bus_init(void)       //driver_init 函数的注释是driver_init - initialize driver model.

 

int __init platform_bus_init(void)
{
 int error;

 error = device_register(&platform_bus);    //

/************

struct device platform_bus = {
 .bus_id  = "platform",
};

这个地方生成了/sys/devices/platform 目录  和devices篇有关联

************/
 if (error)
  return error;
 error =  bus_register(&platform_bus_type);
 if (error)
  device_unregister(&platform_bus);
 return error;
}

主要看error =  bus_register(&platform_bus_type);

 


/**
 * 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 bus_type_private *priv;

 priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
 if (!priv)
  return -ENOMEM;

 priv->bus = bus;
 bus->p = priv;         //这两句将bus结构体的成员struct bus_type_private *p定义了

 BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);

 retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);

//bus->name 是“platform”  ,将priv->subsys.kobj 的name定为“platform”;

 

 


 if (retval)
  goto out;

 priv->subsys.kobj.kset = bus_kset;    //将priv->subsys.kobj.kset定为bus_kset   buses_init();中的bus_kset
 priv->subsys.kobj.ktype = &bus_ktype;
 priv->drivers_autoprobe = 1;               //正因为将其赋值1,所以设备中的bus_attach_device函数中的device_attach(dev)会跑

 retval = kset_register(&priv->subsys);    //在sys/bus/下生成了platform目录
 if (retval)
  goto out;

 retval = bus_create_file(bus, &bus_attr_uevent);

/*******************

找了半天没找到bus_attr_uevent那儿定义的,用SI搜到搜不到,google才发现是这样的:

Bus.c中:static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);

而#define BUS_ATTR(_name, _mode, _show, _store) /
struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)

 

所以这里在platform下面创建了一个名为uevent的文件

 

******************/

 

 


 if (retval)
  goto bus_uevent_fail;

 priv->devices_kset = kset_create_and_add("devices", NULL,
       &priv->subsys.kobj);                                                   //在platform下新建的devicse目录
 if (!priv->devices_kset) {
  retval = -ENOMEM;
  goto bus_devices_fail;
 }

 priv->drivers_kset = kset_create_and_add("drivers", NULL,
       &priv->subsys.kobj);                                                   //在platform下新建的drivers目录
 if (!priv->drivers_kset) {
  retval = -ENOMEM;
  goto bus_drivers_fail;
 }

 klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);   //初始化bus包含的devices链表和drivers链表
 klist_init(&priv->klist_drivers, NULL, NULL);

 retval = add_probe_files(bus);

//调用bus_create_file函数创建drivers_probe和drivers_autoprobe两个文件
 if (retval)
  goto bus_probe_files_fail;

 retval = bus_add_attrs(bus);

//Add default attributes for this 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;
}

 

 

 bus先分析到这儿

 

(责任编辑:IT)
------分隔线----------------------------
栏目列表
推荐内容