devres in linux driver
写 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的更多相关文章
- Linux driver 板级文件跟踪一般方法
/*********************************************************************************** * Linux driver ...
- OK335xS pwm buzzer Linux driver hacking
/**************************************************************************** * OK335xS pwm buzzer L ...
- linux driver开发
1 开发linux driver时的调试思路 基本上是打印调试,原因很简单,方便.或者使用工具挂住cpu.
- linux driver module
本文将对Linux系统中的sysfs进行简单的分析,要分析sysfs就必须分析内核的driver-model(驱动模型),两者是紧密联系的.在分析过程中,本文将以platform总线和spi主控制器的 ...
- linux driver ------ platform模型,驱动开发分析
一.platform总线.设备与驱动 在Linux 2.6 的设备驱动模型中,关心总线.设备和驱动3个实体,总线将设备和驱动绑定.在系统每注册一个设备的时候,会寻找与之匹配的驱动:相反的,在系统每注册 ...
- linux driver ------ GPIO的驱动编写和调用
判断哪些文件被编译进内核: 1.通过 make menuconfig 查看 2.比如查看gpio类型的文件,输入 ls drivers/gpio/*.o,有生成.o文件表示被编译进内核 在编写驱动程序 ...
- linux driver ------ platform模型,通过杂项设备(主设备号是10)注册设备节点
注册完设备和驱动之后,就需要注册设备节点 Linux杂项设备出现的意义在于:有很多简单的外围字符设备,它们功能相对简单,一个设备占用一个主设备号对于内核资源来说太浪费.所以对于这些简单的字符设备它们共 ...
- ad7888 linux driver
/* ADCCONVERT.c : Generate ADC signals from SPI ports, as the A/D control signals. Author: Aaron Fu ...
- linux driver编译环境搭建和命令
首先将ubuntu14.04的内核升级到内核3.18.12. 其次,Ubuntu14.04上驱动编译命令 $ sudo make -C ~/linux-3.18.12/ M=`pwd` modules ...
随机推荐
- java(List或Array数组)求交集、并集、差集, 泛型工具类
业务需要求不同类型的交集.并集.差集为避免代码冗余编写工具类. 注:list 转数组需传入数组,如果将原数组传入将会改变原数组的值,同时泛型数组又不可以实例化,解决方案:Arrays.copyOf(n ...
- js实现复制粘贴功能
在项目中使用到复制粘贴功能,虽然网上有很多大牛封装了很多的插件,但是还是想不去使用插件,就像自己来实现这个功能. 另一篇是禁止复制粘贴 前端er怎样操作剪切复制以及禁止复制+破解等 初步想法: 1. ...
- perl学习之:use & require
相同: 都可以用来引用module(.PM). 不同: 1) 区别在于USE是在当前默认的@INC里面去寻找,一旦模块不在@INC中的话,用USE是不可以引入的,但是require可以指定路径: 2) ...
- 【问题探索日志】python 函数优化
# 事情是这样的,我写的一个程序帧率上不去. 然后发现了一个疑似有问题的地方,如下 def around(x,y): around_dict = {(i,j) for i in range(-1,2) ...
- pytest以函数形式的测试用例
from __future__ import print_function#pytest以函数形式形成测试用例def setup_module(module): print('\nsetup_modu ...
- 【HIHOCODER 1576】 子树中的最小权值(线段树维护DFS序)
描述 给定一棵N个节点的树,编号1~N.其中1号节点是根,并且第i个节点的权值是Vi. 针对这棵树,小Hi会询问小Ho一系列问题.每次小Hi会指定一个节点x,询问小Ho以x为根的子树中,最小的权值是多 ...
- [MVC]Ajax辅助方法
在开始使用Ajax辅助方法前,必须在页面中载入jQuery以及jquery.unobtrusive-ajax.js文件才能正常执行. 为了让网站载入适当的JS函数库,必须先让Layout页面载入适当的 ...
- 大数据学习——mapreduce共同好友
数据 commonfriends.txt A:B,C,D,F,E,O B:A,C,E,K C:F,A,D,I D:A,E,F,L E:B,C,D,M,L F:A,B,C,D,E,O,M G:A,C,D ...
- 大数据学习——下载集群根目录下的文件到E盘
代码如下: package cn.itcast.hdfs; import java.io.IOException; import org.apache.hadoop.conf.Configuratio ...
- [codeforces722C]Destroying Array
[codeforces722C]Destroying Array 试题描述 You are given an array consisting of n non-negative integers a ...