前言 devm是內核提供的基礎機制,用於方便驅動開發者所分配資源的自動回收。參考內核文檔devres.txt。總的來說,就是驅動開發者只需要調用這類介面分配期望的資源,不用關心釋放問題。這些資源的釋放會在device對象銷毀時自動釋放。 devres使用 不同的內核模塊提供了對應的devm_xxx接 ...
前言
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採用零長數組的方式實現。