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 ...
随机推荐
- HDU-5253-链接的管道
http://acm.hdu.edu.cn/showproblem.php?pid=5253 #include <iostream> #include <bits/stdc++.h& ...
- docker 私有镜像服务器搭建
1.准备一台服务器A(已安装docker, IP:192.168.39.111) 2.在服务器A上通过运行registry容器进行搭建 docker run -itd -v /my_registry: ...
- linux下使用docker方式部署ftp服务器
linux环境下部署vsftpd比较繁琐,可以直接使用docker官方仓库中的pure-ftpd镜像来部署ftp服务器. 下载镜像 docker pull stilliard/pure-ftpd:ha ...
- java(List或Array数组)求交集、并集、差集, 泛型工具类
业务需要求不同类型的交集.并集.差集为避免代码冗余编写工具类. 注:list 转数组需传入数组,如果将原数组传入将会改变原数组的值,同时泛型数组又不可以实例化,解决方案:Arrays.copyOf(n ...
- gcc编译详解
GCC(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器.它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分.GCC原本作为GNU操作 ...
- python基础知识08-类定义、属性、初始化和析构
1.类的定义 class 类 是独立存放变量(属性/方法)的一个空间. 每个实例都是一个独立的变量空间.不同实例之间的空间互相不可见. 一个实例的特征,就是属性. 定义在类中的私有属性也可以被子类继承 ...
- LeetCode(14)Longest Common Prefix
题目 Write a function to find the longest common prefix string amongst an array of strings. 分析 该题目是求一个 ...
- 杭电 2647 Reward (拓扑排序反着排)
Description Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to ...
- CSS知识点之字体大小属性font-size
管理文本的大小在 web 设计领域很重要.但是,不应当通过调整文本大小使段落看上去像标题,或者使标题看上去像段落.请始终使用正确的 HTML 标题,比如使用 <h1> - <h6&g ...
- Couchbase V(管理任务)
Couchbase V(管理任务) 多读写 在Couchbase2.1中支持硬盘多读些(Multi- Readers and Writers),一般双核4G服务默认3个thread 4核16G内存一个 ...