Linux设备模型分析之bus

作者:刘昊昱 

博客:http://blog.csdn.net/liuhaoyutz

内核版本:2.6.36

 
前面我们分析了Linux设备模型中kobject、kset以及ktype的使用,它们是设备模型的最基础部分,在其上有更高级一层的bus、device和driver。在这一篇文章中,我们来看一下bus的用法。
 
一、相关数据结构
首先,我们列出本文涉及的相关数据结构。
 51struct bus_type {
 52    const char      *name;
 53    struct bus_attribute    *bus_attrs;
 54    struct device_attribute *dev_attrs;
 55    struct driver_attribute *drv_attrs;
 56
 57    int (*match)(struct device *dev, struct device_driver *drv);
 58    int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
 59    int (*probe)(struct device *dev);
 60    int (*remove)(struct device *dev);
 61    void (*shutdown)(struct device *dev);
 62
 63    int (*suspend)(struct device *dev, pm_message_t state);
 64    int (*resume)(struct device *dev);
 65
 66    const struct dev_pm_ops *pm;
 67
 68    struct bus_type_private *p;
 69};
 
 38struct bus_attribute {
 39    struct attribute    attr;
 40    ssize_t (*show)(struct bus_type *bus, char *buf);
 41    ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
 42};
 
336/* interface for exporting device attributes */
337struct device_attribute {
338    struct attribute    attr;
339    ssize_t (*show)(struct device *dev, struct device_attribute *attr,
340            char *buf);
341    ssize_t (*store)(struct device *dev, struct device_attribute *attr,
342             const char *buf, size_t count);
343};
 
162struct driver_attribute {
163    struct attribute attr;
164    ssize_t (*show)(struct device_driver *driver, char *buf);
165    ssize_t (*store)(struct device_driver *driver, const char *buf,
166             size_t count);
167};
 
  2/**
  3 * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
  4 *
  5 * @subsys - the struct kset that defines this bus.  This is the main kobject
  6 * @drivers_kset - the list of drivers associated with this bus
  7 * @devices_kset - the list of devices associated with this bus
  8 * @klist_devices - the klist to iterate over the @devices_kset
  9 * @klist_drivers - the klist to iterate over the @drivers_kset
 10 * @bus_notifier - the bus notifier list for anything that cares about things
 11 * on this bus.
 12 * @bus - pointer back to the struct bus_type that this structure is associated
 13 * with.
 14 *
 15 * This structure is the one that is the actual kobject allowing struct
 16 * bus_type to be statically allocated safely.  Nothing outside of the driver
 17 * core should ever touch these fields.
 18 */
 19struct bus_type_private {
 20    struct kset subsys;
 21    struct kset *drivers_kset;
 22    struct kset *devices_kset;
 23    struct klist klist_devices;
 24    struct klist klist_drivers;
 25    struct blocking_notifier_head bus_notifier;
 26    unsigned int drivers_autoprobe:1;
 27    struct bus_type *bus;
 28};
 
406struct device {
407    struct device       *parent;
408
409    struct device_private   *p;
410
411    struct kobject kobj;
412    const char      *init_name; /* initial name of the device */
413    struct device_type  *type;
414
415    struct mutex        mutex;  /* mutex to synchronize calls to
416                     * its driver.
417                     */
418
419    struct bus_type *bus;       /* type of bus device is on */
420    struct device_driver *driver;   /* which driver has allocated this
421                       device */
422    void        *platform_data; /* Platform specific data, device
423                       core doesn't touch it */
424    struct dev_pm_info  power;
425
426#ifdef CONFIG_NUMA
427    int     numa_node;  /* NUMA node this device is close to */
428#endif
429    u64     *dma_mask;  /* dma mask (if dma'able device) */
430    u64     coherent_dma_mask;/* Like dma_mask, but for
431                         alloc_coherent mappings as
432                         not all hardware supports
433                         64 bit addresses for consistent
434                         allocations such descriptors. */
435
436    struct device_dma_parameters *dma_parms;
437
438    struct list_head    dma_pools;  /* dma pools (if dma'ble) */
439
440    struct dma_coherent_mem *dma_mem; /* internal for coherent mem
441                         override */
442    /* arch specific additions */
443    struct dev_archdata archdata;
444#ifdef CONFIG_OF
445    struct device_node  *of_node;
446#endif
447
448    dev_t           devt;   /* dev_t, creates the sysfs "dev" */
449
450    spinlock_t      devres_lock;
451    struct list_head    devres_head;
452
453    struct klist_node   knode_class;
454    struct class        *class;
455    const struct attribute_group **groups;  /* optional groups */
456
457    void    (*release)(struct device *dev);
458};
 
123struct device_driver {
124    const char      *name;
125    struct bus_type     *bus;
126
127    struct module       *owner;
128    const char      *mod_name;  /* used for built-in modules */
129
130    bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */
131
132#if defined(CONFIG_OF)
133    const struct of_device_id   *of_match_table;
134#endif
135
136    int (*probe) (struct device *dev);
137    int (*remove) (struct device *dev);
138    void (*shutdown) (struct device *dev);
139    int (*suspend) (struct device *dev, pm_message_t state);
140    int (*resume) (struct device *dev);
141    const struct attribute_group **groups;
142
143    const struct dev_pm_ops *pm;
144
145    struct driver_private *p;
146};

 
二、注册bus
bus的注册接口为bus_register,该函数代码如下:
 872/**
 873 * bus_register - register a bus with the system.
 874 * @bus: bus.
 875 *
 876 * Once we have that, we registered the bus with the kobject
 877 * infrastructure, then register the children subsystems it has:
 878 * the devices and drivers that belong to the bus.
 879 */
 880int bus_register(struct bus_type *bus)
 881{
 882    int retval;
 883    struct bus_type_private *priv;
 884
 885    priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
 886    if (!priv)
 887        return -ENOMEM;
 888
 889    priv->bus = bus;
 890    bus->p = priv;
 891
 892    BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
 893
 894    retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
 895    if (retval)
 896        goto out;
 897
 898    priv->subsys.kobj.kset = bus_kset;
 899    priv->subsys.kobj.ktype = &bus_ktype;
 900    priv->drivers_autoprobe = 1;
 901
 902    retval = kset_register(&priv->subsys);
 903    if (retval)
 904        goto out;
 905
 906    retval = bus_create_file(bus, &bus_attr_uevent);
 907    if (retval)
 908        goto bus_uevent_fail;
 909
 910    priv->devices_kset = kset_create_and_add("devices", NULL,
 911                         &priv->subsys.kobj);
 912    if (!priv->devices_kset) {
 913        retval = -ENOMEM;
 914        goto bus_devices_fail;
 915    }
 916
 917    priv->drivers_kset = kset_create_and_add("drivers", NULL,
 918                         &priv->subsys.kobj);
 919    if (!priv->drivers_kset) {
 920        retval = -ENOMEM;
 921        goto bus_drivers_fail;
 922    }
 923
 924    klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
 925    klist_init(&priv->klist_drivers, NULL, NULL);
 926
 927    retval = add_probe_files(bus);
 928    if (retval)
 929        goto bus_probe_files_fail;
 930
 931    retval = bus_add_attrs(bus);
 932    if (retval)
 933        goto bus_attrs_fail;
 934
 935    pr_debug("bus: '%s': registered\n", bus->name);
 936    return 0;
 937
 938bus_attrs_fail:
 939    remove_probe_files(bus);
 940bus_probe_files_fail:
 941    kset_unregister(bus->p->drivers_kset);
 942bus_drivers_fail:
 943    kset_unregister(bus->p->devices_kset);
 944bus_devices_fail:
 945    bus_remove_file(bus, &bus_attr_uevent);
 946bus_uevent_fail:
 947    kset_unregister(&bus->p->subsys);
 948out:
 949    kfree(bus->p);
 950    bus->p = NULL;
 951    return retval;
 952}

894行,设置priv->subsys.kobj的名字,priv->subsys是一个kset,代表这个bus。bus是通过一个kset来表示的,而device和device_driver都是通过一个kobject来表示的,由此也可以看出他们的不同。
898行,设置priv->subsys.kobj.kset为bus_kset;
在drivers/base/bus.c文件中,162行有如下定义:
162static struct kset *bus_kset;

同时,在buses_init函数中对bus_kset进行了初始化:
1054int __init buses_init(void)
1055{
1056    bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
1057    if (!bus_kset)
1058        return -ENOMEM;
1059    return 0;
1060}

1056行,创建一个名为bus的kset,赋值给bus_kset,对应/sys/bus目录。所有的bus都属性bus_set,即所有的bus对应的sys系统目录都放在/sys/bus目录下。
bus_kset对应的kset_uevent_ops是bus_uevent_ops,其定义如下:
158static const struct kset_uevent_ops bus_uevent_ops = {
159    .filter = bus_uevent_filter,
160};

bus_uevent_filter函数定义如下:
149static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
150{
151    struct kobj_type *ktype = get_ktype(kobj);
152
153    if (ktype == &bus_ktype)
154        return 1;
155    return 0;
156}

回忆一下上一篇博客《Linux设备模型分析之kset》介绍的内容,如果kset_uevent_ops.filter函数返回0,将不会处理uevent事件。在bus_uevent_filter函数中,如果kobj->ktype不是bus_ktype,则返回0,即不处理Uevent事件。
bus_ktype定义如下:
145static struct kobj_type bus_ktype = {
146    .sysfs_ops  = &bus_sysfs_ops,
147};

bus_sysfs_ops定义如下:
119static const struct sysfs_ops bus_sysfs_ops = {
120    .show   = bus_attr_show,
121    .store  = bus_attr_store,
122};

bus_attr_show和bus_attr_store函数定义如下:
  95static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,
  96                 char *buf)
  97{
  98    struct bus_attribute *bus_attr = to_bus_attr(attr);
  99    struct bus_type_private *bus_priv = to_bus(kobj);
 100    ssize_t ret = 0;
 101
 102    if (bus_attr->show)
 103        ret = bus_attr->show(bus_priv->bus, buf);
 104    return ret;
 105}
 106
 107static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr,
 108                  const char *buf, size_t count)
 109{
 110    struct bus_attribute *bus_attr = to_bus_attr(attr);
 111    struct bus_type_private *bus_priv = to_bus(kobj);
 112    ssize_t ret = 0;
 113
 114    if (bus_attr->store)
 115        ret = bus_attr->store(bus_priv->bus, buf, count);
 116    return ret;
 117}

bus_attribute结构体定义如下:
 38struct bus_attribute {
 39    struct attribute    attr;
 40    ssize_t (*show)(struct bus_type *bus, char *buf);
 41    ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
 42};

回到bus_register函数:
899行,设置priv->subsys.kobj.ktype为 &bus_ktype;回忆一下前面的文章《Linux设备模型分析之kobject》,对kobject属性的读写操作将调用kobject.ktype定义的sysfs_ops函数集指定的show和store函数。所以对bus属性文件的读写操作将会调用bus_ktyp.sysfs_ops指定的bus_attr_show和bus_attr_store函数,这两个函数我们前面已经分析过了,他们将回溯到bus_attr->show和bus_attr->store函数。
900行,设置priv->drivers_autoprobe为1;
902行,调用kset_register注册priv->subsys,即注册代表bus的kset。注册完成后,将在/sys/bus目录下出现对应该bus的目录。
906行,调用bus_create_file(bus, &bus_attr_uevent),创建uevent属性文件,该函数定义如下:
 124int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
 125{
 126    int error;
 127    if (bus_get(bus)) {
 128        error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);
 129        bus_put(bus);
 130    } else
 131        error = -EINVAL;
 132    return error;
 133}

128行,调用sysfs_create_file函数创建了bus_attribute对应的属性文件。
先来看bus_attr_uevent的定义,它是通过宏BUS_ATTR生成的:
870static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);

BUS_ATTR定义如下:
44#define BUS_ATTR(_name, _mode, _show, _store)   \
45struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)

__ATTR定义如下:
70#define __ATTR(_name,_mode,_show,_store) { \
71    .attr = {.name = __stringify(_name), .mode = _mode },   \
72    .show   = _show,                    \
73    .store  = _store,                   \
74}

从bus_attr_uevent的定义可以看出,对应的uevent属性只有store接口,没有实现show接口。store接口函数bus_uevent_store定义如下:
 861static ssize_t bus_uevent_store(struct bus_type *bus,
 862                const char *buf, size_t count)
 863{
 864    enum kobject_action action;
 865
 866    if (kobject_action_type(buf, count, &action) == 0)
 867        kobject_uevent(&bus->p->subsys.kobj, action);
 868    return count;
 869}

回到bus_register函数:
910 - 915行,创建名为devices的kset,其parent是priv->subsys.kobj,即在相应bus目录下创建一个devices目录。
917 - 922行,创建名为drivers的kset,其parent是priv->subsys.kobj,即在相应bus目录下创建一个drivers目录。
924行,初始化priv->klist_devices,即devices链表。
925行,初始化priv->klist_drivers,即drivers链表。
927行,调用add_probe_files(bus)函数创建drivers_probe和drivers_autoprobe两个属性文件,该函数定义如下:
 606static int add_probe_files(struct bus_type *bus)
 607{
 608    int retval;
 609
 610    retval = bus_create_file(bus, &bus_attr_drivers_probe);
 611    if (retval)
 612        goto out;
 613
 614    retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);
 615    if (retval)
 616        bus_remove_file(bus, &bus_attr_drivers_probe);
 617out:
 618    return retval;
 619}

bus_create_file函数我们前面已经分析过了,610行,创建drivers_probe属性文件,614行,创建drivers_autoprobe属性文件。其对应的bus_attribute定义如下:
602static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
603static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,
604        show_drivers_autoprobe, store_drivers_autoprobe);

属性文件对应的操作函数定义如下:
 225static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
 226{
 227    return sprintf(buf, "%d\n", bus->p->drivers_autoprobe);
 228}
 229
 230static ssize_t store_drivers_autoprobe(struct bus_type *bus,
 231                       const char *buf, size_t count)
 232{
 233    if (buf[0] == '0')
 234        bus->p->drivers_autoprobe = 0;
 235    else
 236        bus->p->drivers_autoprobe = 1;
 237    return count;
 238}
 239
 240static ssize_t store_drivers_probe(struct bus_type *bus,
 241                   const char *buf, size_t count)
 242{
 243    struct device *dev;
 244
 245    dev = bus_find_device_by_name(bus, NULL, buf);
 246    if (!dev)
 247        return -ENODEV;
 248    if (bus_rescan_devices_helper(dev, NULL) != 0)
 249        return -EINVAL;
 250    return count;
 251}

show_drivers_autoprobe函数用于显示bus->p->drivers_autoprobe的值。
store_drivers_autoprobe函数根据用户的要求设置bus->p->drivers_autoprobe的值。
store_drivers_probe函数245行调用bus_find_device_by_name 在bus上查找用户指定的device,并且在248行调用bus_rescan_devices_helper函数查找匹配device_driver.
回到bus_register函数:
931行,调用bus_add_attrs函数创建bus默认属性文件,该函数定义如下:
 810/**
 811 * bus_add_attrs - Add default attributes for this bus.
 812 * @bus: Bus that has just been registered.
 813 */
 814
 815static int bus_add_attrs(struct bus_type *bus)
 816{
 817    int error = 0;
 818    int i;
 819
 820    if (bus->bus_attrs) {
 821        for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
 822            error = bus_create_file(bus, &bus->bus_attrs[i]);
 823            if (error)
 824                goto err;
 825        }
 826    }
 827done:
 828    return error;
 829err:
 830    while (--i >= 0)
 831        bus_remove_file(bus, &bus->bus_attrs[i]);
 832    goto done;
 833}

820 - 826行,如果bus->bus_attrs指定了bus的默认属性,则创建对应的属性文件。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值