0x00 背景
在最近一次的驱动开发过程中,遇到由于devm接口使用不当导致kernel panic的问题。对于devm系列接口的认识,还停留在接口的简介中,只知道设备卸载时会自动释放申请过的资源。至于具体是如何实现的,还一无所知。devm接口真的有想象中的那么智能吗,这次便来一探究竟。
0x01 原理介绍
这里以regulator注册接口为例,与一般的注册接口相比,devm接口多传入了一个参数:
include/linux/regulator/driver.h
regulator_register(const struct regulator_desc *regulator_desc,
const struct regulator_config *config);
devm_regulator_register(struct device *dev,
const struct regulator_desc *regulator_desc,
const struct regulator_config *config);
在device结构体中,有着这么一个双向链表:
include/linux/device.h
struct device {
/* ... */
struct list_head devres_head;
/* ... */
};
任何由devm接口申请到的资源都会加入到这个双向链表中,在驱动卸载时,只要去遍历这个双向链表,完成资源的释放即可。原理看起来挺简单,接下来看看代码方面是如何实现的吧。
0x02 具体实现
在跟踪具体的函数流程前,我们先来看两个关键的结构体:
drivers/base/devres.c
struct devres_node {
struct list_head entry; //entry将被用来加入上节所说的双向链表中
dr_release_t release; //函数指针,指向资源释放时所用到的函数