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

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

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

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

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

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

前面我们分析了device、driver、bus三种类型,主要是三者的注册与注销,在sysfs中的目录与属性文件创建等内容。

本节就来详细分析下,在设备注册到总线上时,总线是如何为其寻找对应的驱动的;在驱动注册到总线上时,总线又是如何为其寻找对应的设备的。

   本节的实现代码集中在drivers/base/bus.c和drivers/base/dd.c中。

先来回忆下,在device_register()->device_add()中,先是调用bus_add_device()添加device与bus间的联系,并添加bus为device定义的属性,然后会调用bus_probe_device()。

bus_probe_device()会试图为已挂在总线上的该设备寻找对应的驱动。

我们的故事就从这里开始。

[cpp] viewplaincopyprint?

1./** 

2. * bus_probe_device - probe drivers for a new device 

3. * @dev:

 device to probe 

4. * 

5. * - Automatically probe for a driver if the bus allows it. 

6. */  

7.void bus_probe_device(struct device *dev)  

8.{  

9.    struct bus_type *bus = dev->bus;  

10.    int ret;  

11.  

12.    if (bus && bus->p->drivers_autoprobe) {  

13.        ret = device_attach(dev);  

14.        WARN_ON(ret < 0);  

15.    }  

16.}  

bus_probe_device()为总线上的设备寻找驱动。

它先是检查bus->p->drivers_autoprobe,看是否允许自动探测。

允许了才会调用device_attach()进行实际的寻找工作。

说到bus->p->drivers_autoprobe这个变量,它是在bus_type_private中的,在调用bus_register()前都初始化不了,在bus_register()中自动定为1。

所以,除非是用户空间通过drivers_autoprobe属性文件主动禁止,bus总是允许自动探测的,所有的bus都是如此。

[cpp] viewplaincopyprint?

1./** 

2. * device_attach - try to attach device to a driver. 

3. * @dev:

 device. 

4. * 

5. * Walk the list of drivers that the bus has and call 

6. * driver_probe_device() for each pair. If a compatible 

7. * pair is found, break out and return. 

8. * 

9. * Returns 1 if the device was bound to a driver; 

10. * 0 if no matching driver was found; 

11. * -ENODEV if the device is not registered. 

12. * 

13. * When called for a USB interface, @dev->parent->sem must be held. 

14. */  

15.int device_attach(struct device *dev)  

16.{  

17.    int ret = 0;  

18.  

19.    down(&dev->sem);  

20.    if (dev->driver) {  

21.        ret = device_bind_driver(dev);  

22.        if (ret == 0)  

23.            ret = 1;  

24.        else {  

25.            dev->driver = NULL;  

26.            ret = 0;  

27.        }  

28.    } else {  

29.        pm_runtime_get_noresume(dev);  

30.        ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);  

31.        pm_runtime_put_sync(dev);  

32.    }  

33.    up(&dev->sem);  

34.    return ret;  

35.}  

device_attach()在实际绑定之前,会用dev->sem进行加锁。

不错,dev->sem几乎就是为了在设备与驱动绑定或者解除绑定时加锁用的。

还没有看到它在其它地方被调用。

如果在调用device_attach()前就已经有了dev->driver(),就调用device_bind_driver()进行绑定,不然还要调用bus_for_each_drv()进行依次匹配。

至于pm_runtime_get_noresume之类的函数,属于电源管理部分,我们现在先忽略。

[cpp] viewplaincopyprint?

1.static void driver_bound(struct device *dev)  

2.{  

3.    if (klist_node_attached(&dev->p->knode_driver)) {  

4.        printk(KERN_WARNING "%s:

 device %s already bound\n",  

5.            __func__, kobject_name(&dev->kobj));  

6.        return;  

7.    }  

8.  

9.    pr_debug("driver:

 '%s':

 %s:

 bound to device '%s'\n", dev_name(dev),  

10.         __func__, dev->driver->name);  

11.  

12.    if (dev->bus)  

13.        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  

14.                         BUS_NOTIFY_BOUND_DRIVER, dev);  

15.  

16.    klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);  

17.}  

18.  

19.static int driver_sysfs_add(struct device *dev)  

20.{  

21.    int ret;  

22.  

23.    ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,  

24.              kobject_name(&dev->kobj));  

25.    if (ret == 0) {  

26.        ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,  

27.                    "driver");  

28.        if (ret)  

29.            sysfs_remove_link(&dev->driver->p->kobj,  

30.                    kobject_name(&dev->kobj));  

31.    }  

32.    return ret;  

33.}  

34.  

35.static void driver_sysfs_remove(struct device *dev)  

36.{  

37.    struct device_driver *drv = dev->driver;  

38.  

39.    if (drv) {  

40.        sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj));  

41.        sysfs_remove_link(&dev->kobj, "driver");  

42.    }  

43.}  

44.  

45./** 

46. * device_bind_driver - bind a driver to one device. 

47. * @dev:

 device. 

48. * 

49. * Allow manual attachment of a driver to a device. 

50. * Caller must have already set @dev->driver. 

51. * 

52. * Note that this does not modify the bus reference count 

53. * nor take the bus's rwsem. Please verify those are accounted 

54. * for before calling this. (It is ok to call with no other effort 

55. * from a driver's probe() method.) 

56. * 

57. * This function must be called with @dev->sem held. 

58. */  

59.int device_bind_driver(struct device *dev)  

60.{  

61.    int ret;  

62.  

63.    ret = driver_sysfs_add(dev);  

64.    if (!

ret)  

65.        driver_bound(dev);  

66.    return ret;  

67.}  

device_bind_driver()将device与driver绑定。

它调用了两个内部函数。

其中drivers_sysfs_add()负责创建sysfs中driver和device指向对方的软链接。

还有一个与它相对的函数drivers_sysfs_remove()。

driver_bound()则实际将device加入驱动的设备链表。

因为在调用device_bind_driver()之前就已经设置过dev->driver了,所以这样就将device和driver绑定了。

只是这样好像还缺少了什么,不错,之前看到driver时曾定义了drv->probe函数,bus->probe也有类似的功能,这里只是绑定,却没有调用probe函数。

让我们回过头来,继续看如果device_attach()中没有定义dev->driver会怎么样,是用bus_for_each_drv()对bus的驱动链表进行遍历,遍历函数使用__device_attach。

[cpp] viewplaincopyprint?

1.static int __device_attach(struct device_driver *drv, void *data)  

2.{  

3.    struct device *dev = data;  

4.  

5.    if (!

driver_match_device(drv, dev))  

6.        return 0;  

7.  

8.    return driver_probe_device(drv, dev);  

9.}  

不要小看了__device_attach(),就是在__device_attach()中既完成了匹配工作,又完成了绑定工作。

bus_for_each_drv()在遍历中,如果遍历函数返回值不为0,则遍历结束。

所以在__device_attach()找到并绑定了适合的驱动,就会返回1停止遍历,否则继续遍历剩余的驱动。

先来看匹配工作,这是在driver_match_device()中完成的。

[cpp] viewplaincopyprint?

1.static inline int driver_match_device(struct device_driver *drv,  

2.                      struct device *dev)  

3.{  

4.    return drv->bus->match ?

 drv->bus->match(dev, drv) :

 1;  

5.}  

原来driver_match_device()实际是调用drv->bus->match()来完成设备和驱动的匹配的。

其实这也是理所当然。

因为总线不同,总线规范设备、厂商、类设备等定义的规格都不同,也只有bus亲自主持匹配工作。

再具体的就只能等分析具体总线的时候了。

[cpp] viewplaincopyprint?

1.int driver_probe_device(struct device_driver *drv, struct device *dev)  

2.{  

3.    int ret = 0;  

4.  

5.    if (!

device_is_registered(dev))  

6.        return -ENODEV;  

7.  

8.    pr_debug("bus:

 '%s':

 %s:

 matched device %s with driver %s\n",  

9.         drv->bus->name, __func__, dev_name(dev), drv->name);  

10.  

11.    pm_runtime_get_noresume(dev);  

12.    pm_runtime_barrier(dev);  

13.    ret = really_probe(dev, drv);  

14.    pm_runtime_put_sync(dev);  

15.  

16.    return ret;  

17.}  

如果driver_match_device()匹配成功了,__device_attach()就会继续调用driver_probe_devices()完成绑定。

但driver_probe_devices()又是调用really_probe()完成的。

[cpp] viewplaincopyprint?

1.static atomic_t probe_count = ATOMIC_INIT(0);  

2.static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);  

3.  

4.static int really_probe(struct device *dev, struct device_driver *drv)  

5.{  

6.    int ret = 0;  

7.  

8.    atomic_inc(&probe_count);  

9.    pr_debug("bus:

 '%s':

 %s:

 probing driver %s with device %s\n",  

10.         drv->bus->name, __func__, drv->name, dev_name(dev));  

11.    WARN_ON(!

list_empty(&dev->devres_head));  

12.  

13.    dev->driver = drv;  

14.    if (driver_sysfs_add(dev)) {  

15.        printk(KERN_ERR "%s:

 driver_sysfs_add(%s) failed\n",  

16.            __func__, dev_name(dev));  

17.        goto probe_failed;  

18.    }  

19.  

20.    if (dev->bus->probe) {  

21.        ret = dev->bus->probe(dev);  

22.        if (ret)  

23.            goto probe_failed;  

24.    } else if (drv->probe) {  

25.        ret = drv->probe(dev);  

26.        if (ret)  

27.            goto probe_failed;  

28.    }  

29.  

30.    driver_bound(dev);  

31.    ret = 1;  

32.    pr_debug("bus:

 '%s':

 %s:

 bound device %s to driver %s\n",  

33.         drv->bus->name, __func__, dev_name(dev), drv->name);  

34.    goto done;  

35.  

36.probe_failed:

  

37.    devres_release_all(dev);  

38.    driver_sysfs_remove(dev);  

39.    dev->driver = NULL;  

40.  

41.    if (ret !

= -ENODEV && ret !

= -ENXIO) {  

42.        /* driver matched but the probe failed */  

43.        printk(KERN_WARNING  

44.               "%s:

 probe of %s failed with error %d\n",  

45.               drv->name, dev_name(dev), ret);  

46.    }  

47.    /* 

48.     * Ignore errors returned by ->probe so that the next driver can try 

49.     * its luck. 

50.     */  

51.    ret = 0;  

52.done:

  

53.    atomic_dec(&probe_count);  

54.    wake_up(&probe_waitqueue);  

55.    return ret;  

56.}  

really_probe()完成的绑定工作和device_bind_driver()差不多,只是它还会调用bus->probe或者drv->probe中定义的probe函数。

至于在really_probe()中使用probe_count保护,最后调用wake_up(&probe_waitqueue),都是为了进行同步。

[cpp] viewplaincopyprint?

1./** 

2. * driver_probe_done 

3. * Determine if the probe sequence is finished or not. 

4. * 

5. * Should somehow figure out how to use a semaphore, not an atomic variable... 

6. */  

7.int driver_probe_done(void)  

8.{  

9.    pr_debug("%s:

 probe_count = %d\n", __func__,  

10.         atomic_read(&probe_count));  

11.    if (atomic_read(&probe_count))  

12.        return -EBUSY;  

13.    return 0;  

14.}  

15.  

16./** 

17. * wait_for_device_probe 

18. * Wait for device probing to be completed. 

19. */  

20.void wait_for_device_probe(void)  

21.{  

22.    /* wait for the known devices to complete their probing */  

23.    wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);  

24.    async_synchronize_full();  

25.}  

driver_probe_done()检查当前是否有设备正在绑定驱动。

wait_for_device_probe()会阻塞到所有的设备绑定完驱动。

关于bus_probe_device()的过程就分析到这里,下面来看下bus_add_driver()又是怎样做的。

之前我们已经知道driver_register()把绝大部分操作都移到了bus_add_driver()中来。

其中只有一点和设备与驱动的绑定相关,就是对driver_attach()的调用。

[cpp] viewplaincopyprint?

1.int

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

当前位置:首页 > IT计算机 > 电脑基础知识

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

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