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

上传人:b****6 文档编号:13381610 上传时间:2023-06-13 格式:DOCX 页数:28 大小:26.01KB
下载 相关 举报
linux内核部件分析设备驱动模型之driver.docx_第1页
第1页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第2页
第2页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第3页
第3页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第4页
第4页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第5页
第5页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第6页
第6页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第7页
第7页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第8页
第8页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第9页
第9页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第10页
第10页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第11页
第11页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第12页
第12页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第13页
第13页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第14页
第14页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第15页
第15页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第16页
第16页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第17页
第17页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第18页
第18页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第19页
第19页 / 共28页
linux内核部件分析设备驱动模型之driver.docx_第20页
第20页 / 共28页
亲,该文档总共28页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

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

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

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

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

上节我们分析设备驱动模型中的device,主要是drivers/base/core.c,可以说是代码量最大的一个文件。

本节要分析的驱动driver,就要相对简单很多。

原因也很简单,对于driver,我们能定义的公共部分实在不多,能再sysfs中表达的也很少。

本节的分析将围绕drivers/base/driver.c,但头文件仍然是include/linux/device.h和drivers/base/base.h。

先让我们来看看driver的结构。

[cpp] viewplaincopyprint?

1.struct device_driver {  

2.    const char      *name;  

3.    struct bus_type     *bus;  

4.  

5.    struct module       *owner;  

6.    const char      *mod_name;  /* used for built-in modules */  

7.  

8.    bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */  

9.  

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

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

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

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

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

15.    const struct attribute_group **groups;  

16.  

17.    const struct dev_pm_ops *pm;  

18.  

19.    struct driver_private *p;  

20.};  

structdevice_driver就是模型定义的通用驱动结构。

name是驱动名称,但这个name也只是在静态定义的初始名称,实际使用的名称还是由kobject中保管的。

bus执行驱动所在的总线,owner是驱动所在的模块,还有一个所在模块名称mod_name,suppress_bind_attrs定义是否允许驱动通过sysfs决定挂载还是卸载设备。

下面是一系列函数指针,probe是在驱动刚与设备挂接时调用的,remove是在设备卸载时调用的,shutdown是在设备关闭时调用的(说实话我现在还不知道remove和shutdown的区别),suspend是设备休眠时调用的,resume是设备恢复时调用的。

group是属性集合,pm是电源管理的函数集合,p是指向driver_private的指针。

[cpp] viewplaincopyprint?

1.struct driver_private {  

2.    struct kobject kobj;  

3.    struct klist klist_devices;  

4.    struct klist_node knode_bus;  

5.    struct module_kobject *mkobj;  

6.    struct device_driver *driver;  

7.};  

8.#define to_driver(obj) container_of(obj, struct driver_private, kobj)  

与device类似,device_driver把与其它组件联系的大部分结构变量移到structdriver_private中来。

首先是kobj,在sysfs中代表driver目录本身。

klist_devices是驱动下的设备链表,knode_bus是要挂载在总线的驱动链表上的节点。

mkobj是driver与相关module的联系,之前在device_driver结构中已经有指向module的指针,但这还不够,在/sys下你能发现一个module目录,所以驱动所属的模块在sysfs中也有显示,具体留到代码中再看。

driver指针自然是从driver_private指回structdevice_driver的。

[cpp] viewplaincopyprint?

1.struct driver_attribute {  

2.    struct attribute attr;  

3.    ssize_t (*show)(struct device_driver *driver, char *buf);  

4.    ssize_t (*store)(struct device_driver *driver, const char *buf,  

5.             size_t count);  

6.};  

7.  

8.#define DRIVER_ATTR(_name, _mode, _show, _store)    \  

9.struct driver_attribute driver_attr_##_name =       \  

10.    __ATTR(_name, _mode, _show, _store)  

除了以上两个结构,还有structdriver_attribute。

driver_attribute是driver对structattribute的封装,添加了两个特用于device_driver的读写函数。

这种封装看似简单重复,工作量很小,但在使用时却会造成巨大的便利。

 

好,结构介绍完毕,下面看driver.c中的实现。

[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_driver(n);  

9.        dev = dev_prv->device;  

10.    }  

11.    return dev;  

12.}  

13.  

14.int driver_for_each_device(struct device_driver *drv, struct device *start,  

15.               void *data, int (*fn)(struct device *, void *))  

16.{  

17.    struct klist_iter i;  

18.    struct device *dev;  

19.    int error = 0;  

20.  

21.    if (!

drv)  

22.        return -EINVAL;  

23.  

24.    klist_iter_init_node(&drv->p->klist_devices, &i,  

25.                 start ?

 &start->p->knode_driver :

 NULL);  

26.    while ((dev = next_device(&i)) && !

error)  

27.        error = fn(dev, data);  

28.    klist_iter_exit(&i);  

29.    return error;  

30.}  

31.struct device *driver_find_device(struct device_driver *drv,  

32.                  struct device *start, void *data,  

33.                  int (*match)(struct device *dev, void *data))  

34.{  

35.    struct klist_iter i;  

36.    struct device *dev;  

37.  

38.    if (!

drv)  

39.        return NULL;  

40.  

41.    klist_iter_init_node(&drv->p->klist_devices, &i,  

42.                 (start ?

 &start->p->knode_driver :

 NULL));  

43.    while ((dev = next_device(&i)))  

44.        if (match(dev, data) && get_device(dev))  

45.            break;  

46.    klist_iter_exit(&i);  

47.    return dev;  

48.}  

driver_for_each_device()是对drv的设备链表中的每个设备调用一次指定函数。

driver_find_device()是在drv的设备链表中寻找一个设备,寻找使用指定的匹配函数。

这两个函数都不陌生,在之前分析device的core.c中已经见到与它们很类似的函数,只不过那里是遍历设备的子设备链表,这里是遍历驱动的设备链表。

next_device()同样是辅助用的内部函数。

[cpp] viewplaincopyprint?

1.int driver_create_file(struct device_driver *drv,  

2.               struct driver_attribute *attr)  

3.{  

4.    int error;  

5.    if (drv)  

6.        error = sysfs_create_file(&drv->p->kobj, &attr->attr);  

7.    else  

8.        error = -EINVAL;  

9.    return error;  

10.}  

11.  

12.void driver_remove_file(struct device_driver *drv,  

13.            struct driver_attribute *attr)  

14.{  

15.    if (drv)  

16.        sysfs_remove_file(&drv->p->kobj, &attr->attr);  

17.}  

driver_create_file()创建drv下的属性文件,调用sysfs_create_file()实现。

driver_remove_file()删除drv下的属性文件,调用sysfs_remove_file()实现。

[cpp] viewplaincopyprint?

1.static int driver_add_groups(struct device_driver *drv,  

2.                 const struct attribute_group **groups)  

3.{  

4.    int error = 0;  

5.    int i;  

6.  

7.    if (groups) {  

8.        for (i = 0; groups[i]; i++) {  

9.            error = sysfs_create_group(&drv->p->kobj, groups[i]);  

10.            if (error) {  

11.                while (--i >= 0)  

12.                    sysfs_remove_group(&drv->p->kobj,  

13.                               groups[i]);  

14.                break;  

15.            }  

16.        }  

17.    }  

18.    return error;  

19.}  

20.  

21.static void driver_remove_groups(struct device_driver *drv,  

22.                 const struct attribute_group **groups)  

23.{  

24.    int i;  

25.  

26.    if (groups)  

27.        for (i = 0; groups[i]; i++)  

28.            sysfs_remove_group(&drv->p->kobj, groups[i]);  

29.}  

driver_add_groups()在drv目录下添加属性集合,调用sysfs_create_groups()实现。

driver_remove_groups()在drv目录下删除属性集合,调用sysfs_remove_groups()实现。

发现两点问题:

第一,是不是觉得driver_add_groups()不太合适,最好改为driver_create_groups()才搭调。

但不只是driver用driver_add_groups(),device也使用device_add_groups(),不知一处这样做。

第二,有没有发现driver_create_file()是外部函数,driver_add_groups()就是内部函数,也就是说driver只对外提供添加属性的接口,却不提供添加属性集合的接口。

理由吗?

在structdevice_driver()已经专门定义了一个groups变量来添加属性集合,后面就不易再重复提供接口,而且创建属性集合需要的操作远比创建属性费时。

在device中也是这样做的。

另外,driver中只提供管理属性文件的方法,却不提供管理二进制属性文件的方法,这是因为驱动本身没有这种需求,只有部分设备才要求二进制文件表示。

[cpp] viewplaincopyprint?

1.struct device_driver *get_driver(struct device_driver *drv)  

2.{  

3.    if (drv) {  

4.        struct driver_private *priv;  

5.        struct kobject *kobj;  

6.  

7.        kobj = kobject_get(&drv->p->kobj);  

8.        priv = to_driver(kobj);  

9.        return priv->driver;  

10.    }  

11.    return NULL;  

12.}  

13.  

14.void put_driver(struct device_driver *drv)  

15.{  

16.    kobject_put(&drv->p->kobj);  

17.}  

get_driver()增加drv的引用计数,put_driver()减少drv的引用计数。

这都是通过drv->p->kobj来做的。

[cpp] viewplaincopyprint?

1.struct device_driver *driver_find(const char *name, struct bus_type *bus)  

2.{  

3.    struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);  

4.    struct driver_private *priv;  

5.  

6.    if (k) {  

7.        priv = to_driver(k);  

8.        return priv->driver;  

9.    }  

10.    return NULL;  

11.}  

driver_find()从bus的驱动链表中寻找特定名称的driver。

[cpp] viewplaincopyprint?

1./** 

2. * driver_register - register driver with bus 

3. * @drv:

 driver to register 

4. * 

5. * We pass off most of the work to the bus_add_driver() call, 

6. * since most of the things we have to do deal with the bus 

7. * structures. 

8. */  

9.int driver_register(struct device_driver *drv)  

10.{  

11.    int ret;  

12.    struct device_driver *other;  

13.  

14.    BUG_ON(!

drv->bus->p);  

15.  

16.    if ((drv->bus->probe && drv->probe) ||  

17.        (drv->bus->remove && drv->remove) ||  

18.        (drv->bus->shutdown && drv->shutdown))  

19.        printk(KERN_WARNING "Driver '%s' needs updating - please use "  

20.            "bus_type methods\n", drv->name);  

21.  

22.    other = driver_find(drv->name, drv->bus);  

23.    if (other) {  

24.        put_driver(other);  

25.        printk(KERN_ERR "Error:

 Driver '%s' is already registered, "  

26.            "aborting...\n", drv->name);  

27.        return -EBUSY;  

28.    }  

29.  

30.    ret = bus_add_driver(drv);  

31.    if (ret)  

32.        return ret;  

33.    ret = driver_add_groups(drv, drv->groups);  

34.    if (ret)  

35.        bus_remove_driver(drv);  

36.    return ret;  

37.}  

driver_register()将drv注册到系统中。

它真是做得难以预料地简单,所有的工作几乎完全是由bus_add_driver()代为完成的。

但你要注意,在调用driver_register()前,drv->bus一定要预先设置。

device可以不绑定bus,但driver一定要绑定到bus上。

[cpp] viewplaincopyprint?

1.void driver_unregister(struct device_driver *drv)  

2.{  

3.    if (!

drv || !

drv->p) {  

4.        WARN(1, "Unexpected driver unregister!

\n");  

5.        return;  

6.    }  

7.    driver_remove_groups(drv, drv->groups);  

8.    bus_remove_driver(drv);  

9.}  

driver_unregister()将drv从系统中撤销。

大部分工作是调用bus_remove_driver()完成的。

可以看出bus_add_driver()与bus_remove_driver()相对。

driver和bus的联系如此紧密,以至于driver的注册和撤销工作都可以由bus代劳了。

我们需要更进一步的分析。

 

经过调查,我们发现很有一部分driver的代码被移动到了bus.c中。

我们本节是以driver为主,所以接下来会尽量在不惊动bus的情况下,分析存在于bus.c中的driver代码。

 

[cpp] viewplaincopyprint?

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

2.                 char *buf)  

3.{  

4.    struct driver_attribute *drv_attr = to_drv_attr(attr);  

5.    struct driver_private *drv_priv = to_driver(kobj);  

6.    ssize_t ret = -EIO;  

7.  

8.    if (drv_attr->show)  

9.        ret = drv_attr->show(drv_priv->driver, buf);  

10.

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

当前位置:首页 > 工程科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2