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采用零長數組的方式實現。

參考

完!
2014年6月


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM