linux内核部件分析设备驱动模型之bus.docx

上传人:b****5 文档编号:8203228 上传时间:2023-01-29 格式:DOCX 页数:22 大小:25.53KB
下载 相关 举报
linux内核部件分析设备驱动模型之bus.docx_第1页
第1页 / 共22页
linux内核部件分析设备驱动模型之bus.docx_第2页
第2页 / 共22页
linux内核部件分析设备驱动模型之bus.docx_第3页
第3页 / 共22页
linux内核部件分析设备驱动模型之bus.docx_第4页
第4页 / 共22页
linux内核部件分析设备驱动模型之bus.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

linux内核部件分析设备驱动模型之bus.docx

《linux内核部件分析设备驱动模型之bus.docx》由会员分享,可在线阅读,更多相关《linux内核部件分析设备驱动模型之bus.docx(22页珍藏版)》请在冰豆网上搜索。

linux内核部件分析设备驱动模型之bus.docx

linux内核部件分析设备驱动模型之bus

 前面我们分析了设备驱动模型中的device和driver,device和driver本来是不相关的东西,只因为bus的存在,才被联系到了一起。

本节就来看看设备驱动模型中起枢纽作用的bus。

本节的头文件在include/linux/device.h和drivers/base/base.h,实现代码主要在bus.c中。

因为在bus中有很多代码时为了device找到driver或者driver找到device而定义的,本节先尽量忽略这部分,专注于bus的注册和注销,属性定义等内容。

剩下的留到讨论device和driver关系时在分析。

先来看看bus的数据结构。

[cpp] viewplaincopyprint?

1.struct bus_type {  

2.    const char      *name;  

3.    struct bus_attribute    *bus_attrs;  

4.    struct device_attribute *dev_attrs;  

5.    struct driver_attribute *drv_attrs;  

6.  

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

8.    int (*uevent)(struct device *dev, struct kobj_uevent_env *env);  

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

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

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

12.  

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

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

15.  

16.    const struct dev_pm_ops *pm;  

17.  

18.    struct bus_type_private *p;  

19.};  

structbus_type是bus的通用数据结构。

name是bus的名称,注意到这里也是constchar类型的,在sysfs中使用的还是kobj中动态创建的名称,这里的name只是初始名。

bus_attrs是bus为自己定义的一系列属性,dev_attrs是bus为旗下的device定义的一系列属性,drv_attrs是bus为旗下的driver定义的一系列属性。

其中dev_attrs在bus_add_device()->device_add_attrs()中被加入dev目录下,drv_attrs在bus_add_driver()->driver_add_attrs()中被加入driver目录下。

match函数匹配总线中的dev和driver,返回值为1代表匹配成功,为0则失败。

uevent函数用于总线对uevent的环境变量添加,但在总线下设备的dev_uevent处理函数也有对它的调用。

probe函数是总线在匹配成功时调用的函数,bus->probe和drv->probe中只会有一个起效,同时存在时使用bus->probe。

remove函数在总线上设备或者驱动要删除时调用,bus->remove和drv->remove中同样只会有一个起效。

shutdown函数在所有设备都关闭时调用,即在core.c中的device_shutdown()函数中调用,bus->shutdown和drv->shutdown同样只会有一个起效。

suspend函数是在总线上设备休眠时调用。

resume函数是在总线上设备恢复时调用。

pm是structdev_pm_ops类型,其中定义了一系列电源管理的函数。

p是指向bus_type_private的指针,其中定义了将bus同其它组件联系起来的变量。

[cpp] viewplaincopyprint?

1.struct bus_type_private {  

2.    struct kset subsys;  

3.    struct kset *drivers_kset;  

4.    struct kset *devices_kset;  

5.    struct klist klist_devices;  

6.    struct klist klist_drivers;  

7.    struct blocking_notifier_head bus_notifier;  

8.    unsigned int drivers_autoprobe:

1;  

9.    struct bus_type *bus;  

10.};  

11.  

12.#define to_bus(obj) container_of(obj, struct bus_type_private, subsys.kobj)  

structbus_type_private是将bus同device、driver、sysfs联系起来的结构。

subsys是kset类型,代表bus在sysfs中的类型。

drivers_kset代表bus目录下的drivers子目录。

devices_kset代表bus目录下地devices子目录。

klist_devices是bus的设备链表,klist_drivers是bus的驱动链表。

bus_notifier用于在总线上内容发送变化时调用特定的函数,这里略过。

driver_autoprobe标志定义是否允许device和driver自动匹配,如果允许会在device或者driver注册时就进行匹配工作。

bus指针指向structbus_type类型。

使用structbus_type_private可以将structbus_type中的部分细节屏蔽掉,利于外界使用bus_type。

struct driver_private和structdevice_private都有类似的功能。

[cpp] viewplaincopyprint?

1.struct bus_attribute {  

2.    struct attribute    attr;  

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

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

5.};  

6.  

7.#define BUS_ATTR(_name, _mode, _show, _store)   \  

8.struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)  

9.  

10.#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)  

structbus_attribute是bus对structattribute类型的封装,更方便总线属性的定义。

[cpp] viewplaincopyprint?

1.static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,  

2.                 char *buf)  

3.{  

4.    struct bus_attribute *bus_attr = to_bus_attr(attr);  

5.    struct bus_type_private *bus_priv = to_bus(kobj);  

6.    ssize_t ret = 0;  

7.  

8.    if (bus_attr->show)  

9.        ret = bus_attr->show(bus_priv->bus, buf);  

10.    return ret;  

11.}  

12.  

13.static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr,  

14.                  const char *buf, size_t count)  

15.{  

16.    struct bus_attribute *bus_attr = to_bus_attr(attr);  

17.    struct bus_type_private *bus_priv = to_bus(kobj);  

18.    ssize_t ret = 0;  

19.  

20.    if (bus_attr->store)  

21.        ret = bus_attr->store(bus_priv->bus, buf, count);  

22.    return ret;  

23.}  

24.  

25.static struct sysfs_ops bus_sysfs_ops = {  

26.    .show   = bus_attr_show,  

27.    .store  = bus_attr_store,  

28.};  

29.  

30.static struct kobj_type bus_ktype = {  

31.    .sysfs_ops  = &bus_sysfs_ops,  

32.};  

以上应该是我们最熟悉的部分,bus_ktype中定义了bus对应的kset应该使用的kobj_type实例。

与此类似,driver使用的是自定义的driver_ktype,device使用的是自定义的device_ktype。

只是这里仅仅定义了sysfs_ops,并未定义release函数,不知bus_type_private打算何时释放。

[cpp] viewplaincopyprint?

1.int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)  

2.{  

3.    int error;  

4.    if (bus_get(bus)) {  

5.        error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);  

6.        bus_put(bus);  

7.    } else  

8.        error = -EINVAL;  

9.    return error;  

10.}  

11.  

12.void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr)  

13.{  

14.    if (bus_get(bus)) {  

15.        sysfs_remove_file(&bus->p->subsys.kobj, &attr->attr);  

16.        bus_put(bus);  

17.    }  

18.}  

bus_create_file()在bus目录下创建属性文件,bus_remove_file()在bus目录下删除属性文件。

类似的函数在driver和device中都有见到。

[cpp] viewplaincopyprint?

1.static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)  

2.{  

3.    struct kobj_type *ktype = get_ktype(kobj);  

4.  

5.    if (ktype == &bus_ktype)  

6.        return 1;  

7.    return 0;  

8.}  

9.  

10.static struct kset_uevent_ops bus_uevent_ops = {  

11.    .filter = bus_uevent_filter,  

12.};  

13.  

14.static struct kset *bus_kset;  

可以看到这里定义了一个bus_uevent_ops变量,这是kset对uevent事件处理所用的结构,它会用在bus_kset中。

[cpp] viewplaincopyprint?

1.int __init buses_init(void)  

2.{  

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

4.    if (!

bus_kset)  

5.        return -ENOMEM;  

6.    return 0;  

7.}  

在buses_init()中创建了/sys/bus目录,这是一个kset类型,使用了bus_uevent_ops的uevent操作类型。

其实这里的操作不难想象,在devices中我们有一个类似的devices_kset,可以回顾一下。

[cpp] viewplaincopyprint?

1.static struct kset_uevent_ops device_uevent_ops = {  

2.    .filter =   dev_uevent_filter,  

3.    .name =     dev_uevent_name,  

4.    .uevent =   dev_uevent,  

5.};  

6.  

7./* kset to create /sys/devices/  */  

8.struct kset *devices_kset;  

9.  

10.int __init devices_init(void)  

11.{  

12.    devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);  

13.                ...  

14.}  

15.  

16.void device_initialize(struct device *dev)  

17.{  

18.    dev->kobj.kset = devices_kset;  

19.                ...  

20.}  

devices_kset在devices_init()中被创建,使用相应的device_uevent_ops进行uevent处理。

而devices_kset又被设为每个device初始化时使用的kset。

这就不难想象每个device都是以devices_kset为所属kset的,并使用device_uevent_ops中的处理函数。

只是这里还不知bus_kset会在哪里用到,或许是每个bus所属的kset吧,下面会有答案。

[cpp] viewplaincopyprint?

1.static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)  

2.{  

3.    return sprintf(buf, "%d\n", bus->p->drivers_autoprobe);  

4.}  

5.  

6.static ssize_t store_drivers_autoprobe(struct bus_type *bus,  

7.                       const char *buf, size_t count)  

8.{  

9.    if (buf[0] == '0')  

10.        bus->p->drivers_autoprobe = 0;  

11.    else  

12.        bus->p->drivers_autoprobe = 1;  

13.    return count;  

14.}  

15.  

16.static ssize_t store_drivers_probe(struct bus_type *bus,  

17.                   const char *buf, size_t count)  

18.{  

19.    struct device *dev;  

20.  

21.    dev = bus_find_device_by_name(bus, NULL, buf);  

22.    if (!

dev)  

23.        return -ENODEV;  

24.    if (bus_rescan_devices_helper(dev, NULL) !

= 0)  

25.        return -EINVAL;  

26.    return count;  

27.}  

28.  

29.static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);  

30.static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,  

31.        show_drivers_autoprobe, store_drivers_autoprobe);  

这里定义了总线下的两个属性,只写得drivers_probe,和可读写的drivers_autoprobe。

至于其怎么实现的,我们现在还不关心。

[cpp] viewplaincopyprint?

1.static int add_probe_files(struct bus_type *bus)  

2.{  

3.    int retval;  

4.  

5.    retval = bus_create_file(bus, &bus_attr_drivers_probe);  

6.    if (retval)  

7.        goto out;  

8.  

9.    retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);  

10.    if (retval)  

11.        bus_remove_file(bus, &bus_attr_drivers_probe);  

12.out:

  

13.    return retval;  

14.}  

15.  

16.static void remove_probe_files(struct bus_type *bus)  

17.{  

18.    bus_remove_file(bus, &bus_attr_drivers_autoprobe);  

19.    bus_remove_file(bus, &bus_attr_drivers_probe);  

20.}  

add_probe_files()在bus目录下添加drivers_probe和drivers_autoprobe文件。

remove_probe_files()在bus目录下删除drivers_probe和drivers_autoprobe文件。

这两个函数对bus的probe类型属性进行管理,就像add_bind_files/remove_bind_files对driver的bind类型属性进行管理一样。

[cpp] viewplaincopyprint?

1.static ssize_t bus_uevent_store(struct bus_type *bus,  

2.                const char *buf, size_t count)  

3.{  

4.    enum kobject_action action;  

5.  

6.    if (kobject_action_type(buf, count, &action) == 0)  

7.        kobject_uevent(&bus->p->subsys.kobj, action);  

8.    return count;  

9.}  

10.static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);  

上面定义了bus的一个属性uevent,用于bus所在的kset节点主动发起uevent消息。

同样地uevent文件在driver目录中也有见到。

device目录中也有,不过除了store_uevent之外,还增加了show_uevent的功能。

 

[cpp] viewplaincopyprint?

1.static struct device *next_device(struct klist_iter *i)  

2.{  

3.    struct klist_node *n = klist_next(i);  

4.    struct device *dev = NULL;  

5.    struct device_private *dev_prv;  

6.  

7.    if (n) {  

8.        dev_prv = to_device_private_bus(n);  

9.        dev = dev_prv->device;  

10.    }  

11.    return dev;  

12.}  

13.  

14.int bus_for_each_dev(struct bus_type *bus, struct device *start,  

15.         

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1