linux kernel中devres机制

按照惯例!引言!有没有觉得在编写驱动的时候总是要手动kmalloc再kfree很麻烦!不管是申请内存,各种资源的申请之后都需要手动去释放,如果只是加载和卸载的时候还是可以接受的,关键是在处理错误情况的时候,需要仔细的核对释放的顺序和需要释放的内容,既繁琐又容易出错。那么linux kernel有没有给我们提供什么工具来解决这个问题呢!(废话当然有,没有哪来的这片博客)这就是devres了,全程是managed device resource,设备资源管理。

如何使用devres

使用起来很简单了,linux提供了不同的内核模块对应的devm_前缀的接口,只要调用这些接口,这些资源就会在device销毁的时候自动释放。接口列表如下:

CLOCK
devm_clk_get()
devm_clk_put()
devm_clk_hw_register()
devm_of_clk_add_hw_provider()
DMA
dmam_alloc_coherent()
dmam_alloc_attrs()
dmam_declare_coherent_memory()
dmam_free_coherent()
dmam_pool_create()
dmam_pool_destroy()
GPIO
devm_gpiod_get()
devm_gpiod_get_index()
devm_gpiod_get_index_optional()
devm_gpiod_get_optional()
devm_gpiod_put()
devm_gpiochip_add_data()
devm_gpiochip_remove()
devm_gpio_request()
devm_gpio_request_one()
devm_gpio_free()
IIO
devm_iio_device_alloc()
devm_iio_device_free()
devm_iio_device_register()
devm_iio_device_unregister()
devm_iio_kfifo_allocate()
devm_iio_kfifo_free()
devm_iio_triggered_buffer_setup()
devm_iio_triggered_buffer_cleanup()
devm_iio_trigger_alloc()
devm_iio_trigger_free()
devm_iio_trigger_register()
devm_iio_trigger_unregister()
devm_iio_channel_get()
devm_iio_channel_release()
devm_iio_channel_get_all()
devm_iio_channel_release_all()
INPUT
devm_input_allocate_device()
IO region
devm_release_mem_region()
devm_release_region()
devm_release_resource()
devm_request_mem_region()
devm_request_region()
devm_request_resource()
IOMAP
devm_ioport_map()
devm_ioport_unmap()
devm_ioremap()
devm_ioremap_nocache()
devm_ioremap_wc()
devm_ioremap_resource() : checks resource, requests memory on, maps
devm_iounmap()
pcim_iomap()
pcim_iomap_regions()  : do request_region() and iomap() on iple 
pcim_iomap_table()    : array of mapped addresses indexed by BAR
pcim_iounmap()
IRQ
devm_free_irq()
devm_request_any_context_irq()
devm_request_irq()
devm_request_threaded_irq()
devm_irq_alloc_descs()
devm_irq_alloc_desc()
devm_irq_alloc_desc_at()
devm_irq_alloc_desc_from()
devm_irq_alloc_descs_from()
devm_irq_alloc_generic_chip()
devm_irq_setup_generic_chip()
devm_irq_sim_init()
LED
devm_led_classdev_register()
devm_led_classdev_unregister()
MDIO
devm_mdiobus_alloc()
devm_mdiobus_alloc_size()
devm_mdiobus_free()
MEM
devm_free_pages()
devm_get_free_pages()
devm_kasprintf()
devm_kcalloc()
devm_kfree()
devm_kmalloc()
devm_kmalloc_array()
devm_kmemdup()
devm_kstrdup()
devm_kvasprintf()
devm_kzalloc()
MFD
devm_mfd_add_devices()
MUX
devm_mux_chip_alloc()
devm_mux_chip_register()
devm_mux_control_get()
PER-CPU MEM
devm_alloc_percpu()
devm_free_percpu()
PCI
devm_pci_alloc_host_bridge()  : managed PCI host bridge cation
devm_pci_remap_cfgspace() : ioremap PCI configuration space
devm_pci_remap_cfg_resource() : ioremap PCI configuration space 
pcim_enable_device()      : after success, all PCI ops become ged
pcim_pin_device()     : keep PCI device enabled after release
PHY
devm_usb_get_phy()
devm_usb_put_phy()
PINCTRL
devm_pinctrl_get()
devm_pinctrl_put()
devm_pinctrl_register()
devm_pinctrl_unregister()
POWER
devm_reboot_mode_register()
devm_reboot_mode_unregister()
PWM
devm_pwm_get()
devm_pwm_put()
REGULATOR
devm_regulator_bulk_get()
devm_regulator_get()
devm_regulator_put()
devm_regulator_register()
RESET
devm_reset_control_get()
devm_reset_controller_register()
SERDEV
devm_serdev_device_open()
SLAVE DMA ENGINE
devm_acpi_dma_controller_register()
SPI
devm_spi_register_master()
WATCHDOG
devm_watchdog_register_device()

原理

这个功能使用起来真是方便,不过他的原理是怎样的呢?以dmam_alloc_coherent()为例,实际申请得到的是下面这个结构体。
c++
struct dma_devres {
size_t size;
void *vaddr;
dma_addr_t dma_handle;
};

将这些结构体使用链表连接起来,在申请的时候加入链表,销毁对象的时候按照链表中的内容依次释放,就实现了对这些资源的管理。

总结时间

内容太少啦也没啥好总结的,总之新版内核给我们提供的一些新的特性还是要学习使用的,又方便又减少出错,何乐而不为呢?

参考文献
linux documendation:https://www.kernel.org/doc/Documentation/driver-model/devres.txt

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注