bus

来源:互联网 发布:剑网正太捏脸数据下载 编辑:程序博客网 时间:2024/04/29 07:08

"ls" 命令的 "-F" 命令为所列出的每个文件使用后缀来显示文件的类型,后缀 "/" 表示列出的是目录,后缀 "@" 表示列出的是符号链接文件。

1.bus定义

总线是不同IC器件之间相互通讯的通道;在计算机中,一个总线就是处理器与一个或多个不同外设之间的通讯通道;为了设备模型的目的,所有的设备都通过总线相互连接,甚至当它是一个内部的虚拟总线(如,platform总线);例如,设备模型表示在总线和它们控制的设备之间的实际连接;

Linux设备模型中,一个总线由内核结构体struct bus_type描述;其结构定义如下:

struct bus_type

{

 const char*        name;           //总线类型的名称

 struct subsystem     subsys;         //该总线所属的子系统subsystem,代表自身---kset

 struct kset         drivers;        //该总线所使用的驱动程序的集合

 struct kset        devices;        //挂接在该总线上的所有设备的集合

 struct klist            klist_devices;  //挂接在该总线上的所有设备所组成的链表

 struct klist            klist_drivers;  //该总线所使用的驱动程序所组成的链表

 struct bus_attribute*     bus_attrs;      //总线属性

 struct device_attribute*  dev_attrs;      //设备属性

 struct driver_attribute*  drv_attrs;      //驱动程序属性

 //设备驱动程序匹配函数

 int  (*match)(struct device* dev, struct device_driver* drv);

 //热插拔、即插即用、电源管理,等等事件的处理函数

 int  (*uevent)(struct device* dev, char** envp, int num_envp, char* buffer, int buffer_size);

 int  (*probe)(struct device* dev);

 int  (*remove)(struct device* dev);

 void (*shutdown)(struct device* dev);

 int  (*suspend)(struct device* dev, pm_message_t state);

 int  (*resume)(struct device* dev);

};

//其中重点看一下私有成员结构体:  

struct bus_type_private {  

    struct kset subsys;                           //bus内嵌的kset,代表其自身  

    struct kset *drivers_kset;                      

    struct kset *devices_kset;  

    struct klist klist_devices;                   //包含devices链表及其操作函数  

    struct klist klist_drivers;                   //driver链表及其操作函数  

    struct blocking_notifier_head bus_notifier;  

    unsigned int drivers_autoprobe:1;              //匹配成功自动初始化标志  

    struct bus_type *bus;                            

};  

每个bus_type对象都对应/sys/bus目录下的一个子目录,如,PCI总线对应于/sys/bus/pci目录;在每个这样的子目录下存在两个子目录:devices和drivers,分别对应于bus_type结构中的devices和drivers成员,其中,devices子目录描述的是连接在该总线上的所有设备,drivers子目录描述的是该总线所使用的所有驱动程序;/sys/bus目录下的所有子目录都类似;

2.bus初始化和注册

bus的注册在/drivers/base/bus.c里

int __init buses_init(void)

{

        bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);

        return 0;

}

bus_uevent_ops,这是一个uevent的操作集。

struct kset *kset_create_and_add(const char *name,

                                 struct kset_uevent_ops *uevent_ops,

                                 struct kobject *parent_kobj)

//传递进来的参数为("bus", &bus_uevent_ops, NULL)

{

        struct kset *kset;

        int error;

        //创建一个kset容器

        kset = kset_create(name, uevent_ops, parent_kobj);

        

        //注册创建的kset容器

        error = kset_register(kset);

        

        return kset;

}

首先需要创建一个kset容器

static struct kset *kset_create(const char *name,

                                struct kset_uevent_ops *uevent_ops,

                                struct kobject *parent_kobj)

//传递进来的参数为("bus", &bus_uevent_ops, NULL)

{

        struct kset *kset;

        //为kset分配内存

        kset = kzalloc(sizeof(*kset), GFP_KERNEL);

        

        //设置kset中kobject的名字,这里为bus

        kobject_set_name(&kset->kobj, name);

        //设置uevent操作集,这里为bus_uevent_ops

        kset->uevent_ops = uevent_ops;

        //设置父对象,这里为NULL

        kset->kobj.parent = parent_kobj;

        //设置容器操作集

        kset->kobj.ktype = &kset_ktype;

        //设置父容器

        kset->kobj.kset = NULL;

        return kset;

}

//将kset添加到/sys中

int kset_register(struct kset *k)

{

        int err;

        

        //初始化

        kset_init(k);

        //添加该容器

        err = kobject_add_internal(&k->kobj);

        

        kobject_uevent(&k->kobj, KOBJ_ADD);

        return 0;

}

kset_init进行一些固定的初始化操作,里面没有我们需要关心的内容

kobject_add_internal为重要的一个函数,他对kset里kobj的从属关系进行解析,搭建正确的架构

static int kobject_add_internal(struct kobject *kobj)

{

        int error = 0;

        struct kobject *parent;

        //检测kobj是否为空

        if (!kobj)

                return -ENOENT;

        //检测kobj名字是否为空

        if (!kobj->name || !kobj->name[0]) {

                pr_debug("kobject: (%p): attempted to be registered with empty "

                         "name!\n", kobj);

                WARN_ON(1);

                return -EINVAL;

        }

        //提取父对象

        parent = kobject_get(kobj->parent);

        /* join kset if set, use it as parent if we do not already have one */

        //父容器存在则设置父对象

        if (kobj->kset) {//在bus的kset中为空,所以不会进入到下面的代码

                //检测是否已经设置父对象

                if (!parent)

                        //无则使用父容器为父对象

                        parent = kobject_get(&kobj->kset->kobj);

                //添加该kobj到父容器的链表中

                kobj_kset_join(kobj);

                //设置父对象

                kobj->parent = parent;

        }

        pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",

                 kobject_name(kobj), kobj, __func__,

                 parent ? kobject_name(parent) : "<NULL>",

                 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");

        //建立相应的目录

        error = create_dir(kobj);

        kobj->state_in_sysfs = 1;

        return error;

}

至此bus的目录就建立起来了

int bus_register(struct bus_type *bus)  

{  

    int retval;  

    struct bus_type_private *priv;  

    priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);//进入时bus_type->bus_type_private为NULL  

    if (!priv)   //该函数主要是对其的设置  

        return -ENOMEM;  

    priv->bus = bus;      //私有成员的bus回指该bus  

    bus->p = priv;       //初始化bus->p,即其私有属性  

    BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);  

    retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);  //设置该bus的名字,bus是kset的封装//bus_kset即为所有bus的总起始端点  //围绕bus内嵌的kset初始化,和kset的初始化时围绕  

    priv->subsys.kobj.kset = bus_kset; //kobj相似,没有parent时,就会用kset的kobj,此处即是  

    priv->subsys.kobj.ktype = &bus_ktype; //属性操作级别统一为bus_ktype  

    priv->drivers_autoprobe = 1;//设置该标志,当有driver注册时,会自动匹配devices  

 //上的设备并用probe初始化,当有device注册时也同样找到  driver并会初始化  

    retval = kset_register(&priv->subsys);  //注册kset,创建目录结构,以及层次关系  

    retval = bus_create_file(bus, &bus_attr_uevent); //当前bus目录下生成bus_attr_uevent属性文件  

    if (retval)  

        goto bus_uevent_fail;  

    priv->devices_kset = kset_create_and_add("devices", NULL,//初始化bus目录下的devices目录,里面级联了该bus下设备,  

                         &priv->subsys.kobj); //仍然以kset为原型  

    priv->drivers_kset = kset_create_and_add("drivers", NULL,       //初始化bus目录下的drivers目录,里面级联了该bus下设备的driver  

                         &priv->subsys.kobj);  

    klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);//初始化klist_devices里的操作函数成员  

    klist_init(&priv->klist_drivers, NULL, NULL);        //klist_drivers里的操作函数置空  

    retval = add_probe_files(bus);  //增加bus_attr_drivers_probe和bus_attr_drivers_autoprobe 

    retval = bus_add_attrs(bus);    //增加默认的属性文件  

}  

3.bus属性

struct bus_attribute

{

 struct attribute attr;

 ssize_t (*show)(struct bus_type* bus, char* buf);

 ssize_t (*store)(struct bus_type* bus, const char* buf, size_t count);

};

int bus_create_file(struct bus_type* bus, struct bus_attribute* attr):为指定总线添加属性;

void bus_remove_file(struct bus_type* bus, struct bus_attribute* attr):删除指定总线上的指定属性;



原创粉丝点击