Devres是一个内核设施,通过自动释放驱动程序中分配的资源来帮助开发人员。它简化了init/probe/open函数中的错误处理。使用Devres,每个资源分配器都有自己的托管版本,负责资源的 release 和 free。
本文严重依赖内核源代码树中的Documentation/drivermodel/devres.txt文件,该文件处理devres API,并列出了支持的函数及其描述。
使用资源管理函数分配的内存与设备相关联。Devres由一个与struct设备相关联的任意大小内存区域的链表组成。每个devres资源分配器将已分配的资源插入到列表中。资源一直是可用的,直到代码手动释放它,或当设备从系统中分离,或当驱动程序被卸载。每个devres条目都与一个release函数相关联。释放devres有不同的方法。无论如何,所有devres条目在驱动分离时被释放。在释放时,将调用相关的release函数,然后释放devres条目。
下面是驱动程序可用的资源列表:
- 用于私有数据结构的内存
- 中断(IRQs)
- 内存区域分配(request_mem_region())
- 内存区域I/O映射(ioremap())
- 缓冲内存(可能带有DMA映射)
- 不同的框架数据结构: clocks, GPIOs, PWMs, USB phy, regulators, DMA等等
本文讨论的几乎每个函数都有其托管版本。在大多数情况下,为函数的托管版本指定的名称是通过在原始函数名称前加上devm来获得的。例如,devm_kzalloc()是kzalloc()的托管版本。另外,参数保持不变,但是被移到了右边,因为第一个参数是为其分配资源的结构设备。对于非托管版本已经在其参数中给出了struct device的函数,有一个例外:
void *kmalloc(size_t size, gfp_t flags) void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)
当设备与系统分离或设备驱动程序被卸载时,内存将自动释放。如果不再需要内存,可以使用devm_kfree()释放内存。
这是老方法:
ret = request_irq(irq, my_isr, 0, my_name, my_data); if (ret) { dev_err(dev, "Failed to register IRQ. "); ret = -ENODEV; goto failed_register_irq; /* Unroll */ }
这是正确的方法:
ret = devm_request_irq(dev, irq, my_isr, 0, my_name, my_data); if(ret) { dev_err(dev, "Failed to register IRQ. "); return -ENODEV; /* Automatic unroll */ }