设备资源管理模块

1.解决的问题

相信每一个写过Linux driver的工程师,都在probe函数中遇到过上面的困惑:在顺序申请多种资源(IRQ、Clock、memory、regions、ioremap、dma、等等)的过程中,只要任意一种资源申请失败,就要回滚释放之前申请的所有资源。 于是在函数的最后,就一定会出现很多的goto标签,用于释放不同的资源(如上面的exit_free_irq、exit_free_dma、等等)。 在申请资源出错时,小心翼翼的goto到正确的标签上,以便释放已申请资源。

这样在代码中,整个函数被大段的、重复的如下代码充斥。

if (!condition) 
{ 
    err = xxx; 
    goto xxx; 
}

既浪费精力容易出错,也不美观。 有困惑,就有改善的办法。 方法就是Linux设备模型中的device resource management(设备资源管理)。

2.解决的思路

devres提供了一种机制,用资源节点的形式记录它申请的资源,并在系统中为设备分配一个链表,当申请某个资源时,就构建一个资源节点,然后把它加入到这个链表中,对应的释放函数也会被记录,以便在driver detach的时候,自动释放。

为了使用devres机制,资源要对各自的资源分配函数重新封装,加入资源节点的申请、添加和释放,一般新函数名改成了devm_xxx()的形式。driver作者只管调用这些devm_xxx()接口来申请资源,不用考虑释放,设备模型会在适当的时候释放它们。

device resource management位于“drivers/base/devres.c”中,它实现了上述机制。 1.png

3.提供的接口

以下是devres提供的几个基本接口

interface Description
devres_alloc( ) // 分配资源节点
devres_free( ) // 释放资源节点
devres_add( ) // 添加资源节点到链表
devres_destroy( ) // 释放资源
devres_release_all() //释放所有资源

4.接口的使用

其他资源模块,可以通过调用devres提供的接口,利用devres机制实现资源的自动释放。

4.1 资源节点函数的应用举例

下面的代码是利用devres机制实现分配中断资源函数 devm_request_threaded_irq( ), 上层模块可以调用它来分配中断资源,在出错时,不必考虑对该资源的释放,系统会自动释放。

主要涉及到devres_alloc()、devres_free()和devres_add()

2.png

4.2 资源释放函数的应用举例

资源释放函数devres_destroy()的使用举例,资源模块可以用它来封装资源释放函数。

3.png

5. 函数的内部实现

5.1 devres_alloc()

devrs_alloc()函数的实现,主要调用了内部函数alloc_dr(), 它会分配size+sizeof(struct devres)的内存大小, struct devres用于存储资源节点信息,并记录release 函数。

4.png

5.2 devres_add()

devres_add()主要实现把资源节点添加到设备的资源链表中。

5.png

5.3 devres_destroy()

devres_destroy()主要涉及到以下几个内部函数:

  • devres_remove() //查找到资源节点,并从链表中删除
  • find_dr() //根据release函数指针、match函数查找资源节点
  • devres_free() //释放资源节点

可以结合上面它的使用实例来学习。

6.png

5.4 devers_release_all()

devers_release_all()的调用会释放所有资源。它的被调用时机有两个:

  • really_probe()失败
  • 设备与驱动分离时, deriver_dettach时 就是driver_remove时。

7.png

results matching ""

    No results matching ""