前言
devm是內核提供的基礎機制,用於方便驅動開發者所分配資源的自動回收。參考內核文檔devres.txt。總的來說,就是驅動開發者只需要調用這類接口分配期望的資源,不用關心釋放問題。這些資源的釋放會在device對象銷毀時自動釋放。
devres使用
不同的內核模塊提供了對應的devm_xxx接口,如下(不僅僅這些):
MEM
devm_kmalloc()
devm_kzalloc()
devm_kcalloc()
devm_kmalloc_array()
devm_kstrdup()
devm_kfree()
IIO
devm_iio_device_alloc()
devm_iio_device_free()
devm_iio_trigger_alloc()
devm_iio_trigger_free()
devm_iio_device_register()
devm_iio_device_unregister()
IO region
devm_request_region()
devm_request_mem_region()
devm_release_region()
devm_release_mem_region()
IRQ
devm_request_irq()
devm_free_irq()
DMA
dmam_alloc_coherent()
dmam_free_coherent()
dmam_alloc_noncoherent()
dmam_free_noncoherent()
dmam_declare_coherent_memory()
dmam_pool_create()
dmam_pool_destroy()
PCI
pcim_enable_device() : after success, all PCI ops become managed
pcim_pin_device() : keep PCI device enabled after release
IOMAP
devm_ioport_map()
devm_ioport_unmap()
devm_ioremap()
devm_ioremap_nocache()
devm_iounmap()
devm_ioremap_resource() : checks resource, requests memory region, ioremaps
devm_request_and_ioremap() : obsoleted by devm_ioremap_resource()
pcim_iomap()
pcim_iounmap()
pcim_iomap_table() : array of mapped addresses indexed by BAR
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
REGULATOR
devm_regulator_get()
devm_regulator_put()
devm_regulator_bulk_get()
devm_regulator_register()
CLOCK
devm_clk_get()
devm_clk_put()
PINCTRL
devm_pinctrl_get()
devm_pinctrl_put()
PWM
devm_pwm_get()
devm_pwm_put()
PHY
devm_usb_get_phy()
devm_usb_put_phy()
SLAVE DMA ENGINE
devm_acpi_dma_controller_register()
SPI
devm_spi_register_master()
內核提供了devres_xxx的機制,並基於devres_xxx又給出了devres group機制。devres group主要用於處理初始化的時候,有多種資源類型需要初始化,每種資源類型的初始化又由多個devres_xxx資源申請組成的情況,將這些devres_xxx按類別組合成group,這樣在需要顯示釋放某一類的資源時,調用devres group的api即可實現。內核給出的例子:
if (!devres_open_group(dev, NULL, GFP_KERNEL))//啟動group
return -ENOMEM;
acquire A;//申請資源A
if (failed)
goto err;
acquire B;//申請資源B
if (failed)
goto err;
...
devres_remove_group(dev, NULL);//如果一切順利,那么關掉group
return 0;
err:
devres_release_group(dev, NULL);//如果出錯,那么釋放掉啟動group后所有申請的資源
return err_code;
實現原理
具體的實現很簡單,當然我們應該也能猜測到。在分配內存的時候,會分配比我們要求大的空間,空間的前面部分用於存放實現devres機制的數據結構,然后返回的是用戶期望的空間的指針(該指針是實際分配的空間指針的devres結構的偏移)。
struct devres_node {
struct list_head entry;//通過該成員,掛接到device的devres鏈表上
dr_release_t release;//對應的資源釋放回調
};
struct devres {
struct devres_node node;
/* -- 3 pointers */
unsigned long long data[]; /* guarantee ull alignment *///實際的數據部分
};
devres采用零長數組的方式實現。
參考
- The managed resource API
- Move resources allocated using unmanaged interface to managed devm interface
完!
2014年6月
