写 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. Day02:我的Python学习之路

    1.初识模块 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,现在简单的学习2个常见的标准库——sys和os. (1)系统的标准库sys # Author:GCL # 系统的标准库sy ...

  2. (1) LVS基本概念和三种模式

    网站架构中,负载均衡技术是实现网站架构伸缩性的主要手段之一. 所谓"伸缩性",是指可以不断向集群中添加新的服务器来提升性能.缓解不断增加的并发用户访问压力.通俗地讲,就是一头牛拉不 ...

  3. Go:反射

    一.通过反射获取类型信息 在 Go 程序中,使用 reflect.TypeOf() 函数可以获得任意值的类型对象(reflect.Type),程序通过类型对象可以访问任意值的类型信息. package ...

  4. 如何用纯 CSS 为母亲节创作一颗像素画风格的爱心

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/LmrZVX 可交互视频教 ...

  5. python常用模块之sys, os, random

    一. sys模块 1. 作用: sys模块是与python解释器交互的一个接口 2. 具体使用 1. sys.argv 获取当前正在执行的命令行列表, 第一个为程序本身路径 print('file n ...

  6. python接口自动化-multipart/form-data上传图片

    前言 在提交表单操作的时候,经常会遇到图片上传的操作,图片上传是一个单独的接口,本篇以禅道为例,介绍如何上传图片 上传接口 1.以禅道上提交bug为例,在选择图片时,点确定按钮,就是上传图片了 2.用 ...

  7. 2016上海站EC-final总结!

    2016上海站EC-final总结 本想在知乎上发起一个话题:没有半点准备实力菜得抠脚的选手突然有机会参加final是什么体验.不过感觉这样太高调了,于是..... 以上说的就是事实,毫无准备.毫无状 ...

  8. HUD-1559 最大子矩阵,dp模拟

    最大子矩阵                                                                                               ...

  9. HDU-1020-Encoding,题意不清,其实很水~~

    Encoding Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) http:// ...

  10. [Docker]容器的隔离与限制

    1.Docker事实 1)容器技术的兴起源于Pass技术的普及 2)Docker公司发布的Docker项目具有里程碑式的意义 3)Docker项目通过容器镜像解决了应用打包这个根本性难题 4)容器本身 ...