写 driver 时, probe 中常常要为设备分配一些资源, 如 内存 / irq / gpio / iomap 等. 而在 probe 中失败时又要小心的释放掉这些资源. 底层驱动开发人员可能会把大部分精力放在 probe 成功的处理流程上, 而失败的情况可能出现的较少以致于忘记测试. 这导致的一个问题是当设备加载失败时, 系统中会遗留许多与之相关的资源.

为了干净优雅的处理这种问题, 驱动模型中引入了 devres 机制. 在为 device 分配资源的时候记录下它们, 等到 device detach 的时候, 就可以统一释放.

devres 是一种资源管理机制, 类似于一种垃圾收集处理器. 而资源的处理时机在 driver 的 install / remove 时候. 这样我们在为 device 分配相关资源之后, 就不必要关心如何释放它们了. 与 device 相关的资源有 memory / dma / iomap / regmap / interrupt / gpio 等, 这些资源都可以用 devres 机制管理起来, 使用相关资源封闭的 devres 接口, 就可以让这些资源自动销毁.

API: drivers/base/devres.c

1. void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
申请 "sizeof(struct devres) + size" 大小的内存, size 是指resource的大小. 清0内存, 初始化链表节点 dr->node.entry, 返回 resouce 的指针.

2. void devres_free(void *res)
由 resource 指针定位到 devres 结构体指针, 然后 kfree 掉.

3. void devres_add(struct device *dev, void *res)
将 res 对应的 devres 结构体加入到 dev 的资源管理链表 dev->devres_head 上.

4. void * devres_find(struct device *dev, dr_release_t release, dr_match_t match, void *match_data)
在 dev->devres_head 链表中查找 release / match_data 都匹配的 devres 结构. 并返回 devres 中的 resource 指针 dr->data.

5. void * devres_get(struct device *dev, void *new_res, dr_match_t match, void *match_data)
在 dev->devres_head 中查找 new_res 这个资源是否已经存在, 如果没找到, 则把 new_res 添加到链表中. 如果找到了, 则销毁 new_dr.

6. void * devres_remove(struct device *dev, dr_release_t release, dr_match_t match, void *match_data)
在 dev->devres_head 链表中查找 release / match_data 都匹配的 devres 结构. 并将其中 dev->devres_head 链表中移除.

7. int devres_destroy(struct device *dev, dr_release_t release, dr_match_t match, void *match_data)
在 devices 管理的资源中找到匹配的, 然后移除并销毁它.

8. int devres_release_all(struct device *dev)
release_nodes() 先将 [first, end] 区间的所有节点都移动到todo链表里, 然后删除todo链表(kfree 掉todo链表的所有节点).
devres_release_all()会在device detach时或 device 的 probe 失败时调用. 如此一来, 我们只需分配资源, 无需再关心资源释放了.
这个函数的调用也是 devres 机制的关键所在.

删除链表的时候使用到了 list_for_each_entry_safe_reverse() , 这个宏安全在哪里?
遍历链表的过程中, 我们可能会删除节点. 这个宏 safe 在于它会先记录下一个节点, 然后再操作当前节点. 这样如果当前节点被del掉了, 下一个节点还是可以安全的访问到.

9. void * devres_open_group(struct device *dev, void *id, gfp_t gfp)

10. void devres_close_group(struct device *dev, void *id)

11. void devres_remove_group(struct device *dev, void *id)

12. int devres_release_group(struct device *dev, void *id)

使用到 devres 机制的模块:

drivers/base/dma-mapping.c
kernel/irq/devres.c
mm/dmapool.c
drivers/gpio/devres.c
drivers/base/regmap/regmap.c
drivers/regulator/core.c
drivers/base/regmap/regmap.c
drivers/base/devres.c
drivers/pci/pci.c

参考文献:
Documentation/driver-model/devres.txt
http://lwn.net/Articles/222860/

devres in linux driver的更多相关文章

  1. Linux driver 板级文件跟踪一般方法

    /*********************************************************************************** * Linux driver ...

  2. OK335xS pwm buzzer Linux driver hacking

    /**************************************************************************** * OK335xS pwm buzzer L ...

  3. linux driver开发

    1 开发linux driver时的调试思路 基本上是打印调试,原因很简单,方便.或者使用工具挂住cpu.

  4. linux driver module

    本文将对Linux系统中的sysfs进行简单的分析,要分析sysfs就必须分析内核的driver-model(驱动模型),两者是紧密联系的.在分析过程中,本文将以platform总线和spi主控制器的 ...

  5. linux driver ------ platform模型,驱动开发分析

    一.platform总线.设备与驱动 在Linux 2.6 的设备驱动模型中,关心总线.设备和驱动3个实体,总线将设备和驱动绑定.在系统每注册一个设备的时候,会寻找与之匹配的驱动:相反的,在系统每注册 ...

  6. linux driver ------ GPIO的驱动编写和调用

    判断哪些文件被编译进内核: 1.通过 make menuconfig 查看 2.比如查看gpio类型的文件,输入 ls drivers/gpio/*.o,有生成.o文件表示被编译进内核 在编写驱动程序 ...

  7. linux driver ------ platform模型,通过杂项设备(主设备号是10)注册设备节点

    注册完设备和驱动之后,就需要注册设备节点 Linux杂项设备出现的意义在于:有很多简单的外围字符设备,它们功能相对简单,一个设备占用一个主设备号对于内核资源来说太浪费.所以对于这些简单的字符设备它们共 ...

  8. ad7888 linux driver

    /* ADCCONVERT.c : Generate ADC signals from SPI ports, as the A/D control signals. Author:  Aaron Fu ...

  9. linux driver编译环境搭建和命令

    首先将ubuntu14.04的内核升级到内核3.18.12. 其次,Ubuntu14.04上驱动编译命令 $ sudo make -C ~/linux-3.18.12/ M=`pwd` modules ...

随机推荐

  1. 浅谈Link-Cut Tree(LCT)

    0XFF 前言&概念 Link-Cut Tree 是一种用来维护动态森林连通性的数据结构,适用于动态树问题.它采用类似树链剖分的轻重边路径剖分,把树边分为实边和虚边,并用 Splay 来维护每 ...

  2. python测试工具

    https://wiki.python.org/moin/PythonTestingToolsTaxonomy mac pip安装 https://blog.csdn.net/ywj_486/arti ...

  3. 项目如何发布到tomcat

    在eclipse上export 出WAR file 然后将文件放到tomcat中的webapps 上即可.

  4. Android开发——后台获取用户点击位置坐标(可获取用户支付宝密码)

    1. getevent命令 我们首先是根据adb shell getevent命令获取到被点击位置的信息. 这里要说明的是,不同的手机手机获得的点击输出是不一样的.以我的真机为例,输出如下 本文原创, ...

  5. UI进阶 XML解析适配 'libxml/tree.h'file not found 错误解决办法

    Xcode 'libxml/tree.h'file not found 错误解决办法

  6. [HNOI2004]宠物收养场(Treap)

    洛谷传送门 这题真是恶心,一开始没理解题意. 原来如果有狗,狗就会存在收养场中,直到有人来领养: 如果有人,人也会存在收养场中,直到有狗来被领养. 就是建一个treap,狗来把狗插进去,人来后把狗领养 ...

  7. Enchantress(hdu 3922)

    首先考虑覆盖三个点的情况,有两种情况: ①:三个点都在圆上,则该圆是三角形的外接圆 ②:两个点在圆上,第三个点在圆内,且在圆上的两个点之间的线段一定是直径 如果是多个圆,就不停地迭代. 有一点重要的是 ...

  8. CodeForces - 601A The Two Routes

    http://codeforces.com/problemset/problem/601/A 这道题没想过来, 有点脑筋急转弯的感觉了 本质上就是找最短路径 但是卡在不能重复走同一个点 ----> ...

  9. [CodePlus2017]汀博尔

    Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 158  Solved: 61[Submit][Status][Discuss] Description ...

  10. Codeforces827D. Best Edge Weight

    $n \leq 2e5,m \leq 2e5$的有边权图,对每条边问:不改其他边的情况下这条边最多能是多少使得他一定在所有最小生成树上,如果无穷大输出-1. 典型题+耗时题,CF上的绝望时刻..打VP ...