写 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. [POJ] 3539 Elevator

    http://poj.org/problem?id=3539 给定一个电梯,可以上升a,b,c层和回到1层,给定楼高h,求可达层数 lyd讲的同余类BFS,方法是先把三个量压成两个,即把h%a,因为对 ...

  2. Java:获取IP地址

    文章来源:https://www.cnblogs.com/hello-tl/p/9139323.html import java.net.InetAddress; import java.net.Un ...

  3. LeetCode(73)Set Matrix Zeroes

    题目 Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. cli ...

  4. Codeforces Round #211 (Div. 2)-D. Renting Bikes,二分!感谢队友出思路!

    D. Renting Bikes 读懂题后一开始和队友都以为是贪心.可是贪心又怎么贪呢..我们无法确定到底能买多少车但肯定是最便宜的前x辆.除了公共预算每个人的钱只能自己用,也无法确定每个人买哪一辆车 ...

  5. oracle 9i/10g/11g(11.2.0.3)安装包和PATCH下载地址汇总

    今天上PUB看见一位热心人汇总了这么个地址列表,转发来空间: 把下面的地址复制到讯雷里就可以下载. -------------------------------------------------- ...

  6. [Poi2011]Meteors 题解

    题目大意: 给定一个环,每个节点有一个所属国家,k次事件,每次对[l,r]区间上的每个点点权加上一个值,求每个国家最早多少次操作之后所有点的点权和能达到一个值. 思路: 整体二分(二分答案),对于每个 ...

  7. 深入理解ajax系列第五篇

    前面的话 一般地,使用readystatechange事件探测HTTP请求的完成.XHR2规范草案定义了进度事件Progress Events规范,XMLHttpRequest对象在请求的不同阶段触发 ...

  8. [NOIP2003] 普及组

    乒乓球 模拟 /*By SilverN*/ #include<iostream> #include<algorithm> #include<cstring> #in ...

  9. [NOIP2001] 提高组 洛谷P1024 一元三次方程求解

    题目描述 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差 ...

  10. Linux下增加User及添加sudo权限

    运行adduser username 会默认建立同名的user,group,同时会要求输入用户密码及一些属性,完成之后OK. sudo chmod +w /etc/sudoers vi /etc/su ...