本文转载自:http://blog.csdn.net/jgw2008/article/details/52691568

函数 devm_kzalloc() 和kzalloc()一样都是内核内存分配函数,但是devm_kzalloc()是跟设备(device)有关的,当设备(device)被detached或者驱动(driver)卸载(unloaded)时,内存会被自动释放。另外,当内存不在使用时,可以使用函数devm_kfree()释放。
而kzalloc()则需要手动释放(使用kfree()),但如果工程师检查不仔细,则有可能造成内存泄漏。
下面是devm_kzalloc()的实现,
  1. /* managed devm_k.alloc/kfree for device drivers */
  2. extern void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp);
  3. static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
  4. {
  5. return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
  6. }
 
  1. /**
  2. * devm_kmalloc - Resource-managed kmalloc
  3. * @dev: Device to allocate memory for
  4. * @size: Allocation size
  5. * @gfp: Allocation gfp flags
  6. *
  7. * Managed kmalloc.  Memory allocated with this function is
  8. * automatically freed on driver detach.  Like all other devres
  9. * resources, guaranteed alignment is unsigned long long.
  10. *
  11. * RETURNS:
  12. * Pointer to allocated memory on success, NULL on failure.
  13. */
  14. void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)
  15. {
  16. struct devres *dr;
  17. /* use raw alloc_dr for kmalloc caller tracing */
  18. dr = alloc_dr(devm_kmalloc_release, size, gfp);
  19. if (unlikely(!dr))
  20. return NULL;
  21. /*
  22. * This is named devm_kzalloc_release for historical reasons
  23. * The initial implementation did not support kmalloc, only kzalloc
  24. */
  25. set_node_dbginfo(&dr->node, "devm_kzalloc_release", size);
  26. devres_add(dev, dr->data);
  27. return dr->data;
  28. }
  29. EXPORT_SYMBOL_GPL(devm_kmalloc);
Stackoverflow上面解释的很好,
http://stackoverflow.com/questions/12256986/what-is-the-difference-between-devm-kzalloc-and-kzalloc-in-linux-driver-prog
devm_kzalloc() is resource-managed kzalloc(). The memory allocated with resource-managed functions is associated with the device. When the device is detached from the system or the driver for the device is unloaded, that memory is freed automatically. It is possible to free the memory with devm_kfree() if it's no longer needed.
下面的例子也很好

Move resources allocated using unmanaged interface to managed devm interface

So today let’s talk about devm functions as that is what I have been upto the past couple of weeks. Yes, should have finished the task by now but due to some reasons was not active a couple of days :(.
Now what are devm functions. There are some common memory resources used by drivers which are allocated using functions and stored as a linked list of arbitrarily sized memory areas called devres. Some of this memory is allocated in the probe function. But all of this memory should be freed on a failure path or a driver detach. Else, the driver will be leaking resources and wasting precious main memory!
Detection of such memory leaks is difficult as they not clearly noticeable. So, managed interfaces have been created for common resources used by drivers. They have a name similar to the corresponding unmanaged function making it easy to identify e.g.:  dma_alloc_coherent() and dmam_alloc_coherent(), kzalloc() and devm_kzalloc(). If a managed function is used for memory allocation the resources are guaranteed to be freed both on initialization failure and driver detachment. Many of these managed functions are devm functions. eg: devm_kzalloc, devm_iio_device_alloc().
My task has been mainly to identify the cases where kzalloc() can be changed to devm_kzalloc() and the corresponding kfree()s can be done away with. Then the changes were applied and minor code changes like removal of labels , removing of brackets in single statement ifs were done. I have been using a Coccinelle semantic patch to do this task and have made tweaks to handle some specific cases. Here is a major part of the Coccinelle semantic patch making the change:

@platform@
identifier p, probefn, removefn;
@@
struct platform_driver p = {
.probe = probefn,
.remove = removefn,
};

@prb@
identifier platform.probefn, pdev;
expression e, e1, e2;
@@
probefn(struct platform_device *pdev, …) {
<+…
- e = kzalloc(e1, e2)
+ e = devm_kzalloc(&pdev->dev, e1, e2)

?-kfree(e);
…+>
}

@rem depends on prb@
identifier platform.removefn;
expression e;
@@
removefn(…) {
<…
- kfree(e);
…>
}

There are many cases in which a lot of code goes away and the probe and remove functions appear really simple and easier to understand.
At the same time, there are issues such as cases to which the patch applies but does not benefit much as there are major resources that are still unmanaged. Also, some more advanced functions that can be managed like IRQs have not been handled at this stage.

The managed resource API

[Posted February 20, 2007 by corbet]

The device resource managementpatch was discussed here in January. That patch has now been mergedfor the 2.6.21 kernel. Since the API is now set - at least, as firmly asany in-kernel API is - it seems like a good time for a closer look at thisnew interface.

The core idea behind the resource management interface is that remembering to freeallocated resources is hard. It appears to be especially hard for driverwriters who, justly or not, have a reputation for adding more than theirfair share of bugs to the kernel. And even the best driver writers can runinto trouble in situations where device probing fails halfway through; therecovery paths may be there in the code, but they tend not to be welltested. The result of all this is a fair number of resource leaks indriver code.

To address this problem, Tejun Heo created a new set of resource allocationfunctions which track allocations made by the driver. These allocationsare associated with the device structure; when the driver detachesfrom the device, any left-over allocations are cleaned up. The resourcemanagement interface is thus similar to thetalloc()API used by the Samba hackers, but it is adapted to the kernelenvironment and covers more than just memory allocations.

Starting with memory allocations, though, the new API is:

    void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
void devm_kfree(struct device *dev, void *p);

In a pattern we'll see repeated below, the new functions are similar tokzalloc() and kfree() except for the new names and theaddition of the dev argument. That argument is necessary for theresource management code to know when the memory can be freed. If anymemory allocations are still outstanding when the associated device isremoved, they will all be freed at that time.

Note that there is no managed equivalent to kalloc(); if driverwriters cannot be trusted to free memory, it seems, they cannot be trustedto initialize it either. There are also no managed versions of thepage-level or slab allocation functions.

Managed versions of a subset of the DMA allocation functions have beenprovided:

    void *dmam_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp);
void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle);
void *dmam_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp);
void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle);
int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size,
int flags);
void dmam_release_declared_memory(struct device *dev);
struct dma_pool *dmam_pool_create(const char *name, struct device *dev,
size_t size, size_t align,
size_t allocation);
void dmam_pool_destroy(struct dma_pool *pool);

All of these functions have the same arguments and functionality as theirdma_* equivalents, but they will clean up the DMA areas on deviceshutdown. One still has to hope that the driver has ensuredthat no DMA remains active on those areas, or unpleasant things couldhappen.

There is a managed version of pci_enable_device():

    int pcim_enable_device(struct pci_dev *pdev);

There is no pcim_disable_device(), however; code should just usepci_disable_device() as usual. A new function:

    void pcim_pin_device(struct pci_dev *pdev);

will cause the given pdev to be left enabled even after the driverdetaches from it.

The patch makes the allocation of I/O memory regions withpci_request_region() managed by default - there is nopcim_ version of that interface. The higher-level allocation andmapping interfaces do have managed versions:

    void __iomem *pcim_iomap(struct pci_dev *pdev, int bar,
unsigned long maxlen);
void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);

For the allocation of interrupts, the managed API is:

    int devm_request_irq(struct device *dev, unsigned int irq,
irq_handler_t handler, unsigned long irqflags,
const char *devname, void *dev_id);
void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);

For these functions, the addition of a struct device argument wasrequired.

There is a new set of functions for the mapping of of I/O ports and memory:

    void __iomem *devm_ioport_map(struct device *dev, unsigned long port,
unsigned int nr);
void devm_ioport_unmap(struct device *dev, void __iomem *addr);
void __iomem *devm_ioremap(struct device *dev, unsigned long offset,
unsigned long size);
void __iomem *devm_ioremap_nocache(struct device *dev,
unsigned long offset,
unsigned long size);
void devm_iounmap(struct device *dev, void __iomem *addr);

Once again, these functions required the addition of a structdevice argument for the managed form.

Finally, for those using the low-level resource allocation functions, themanaged versions are:

    struct resource *devm_request_region(struct device *dev,
resource_size_t start,
resource_size_t n,
const char *name);
void devm_release_region(resource_size_t start, resource_size_t n);
struct resource *devm_request_mem_region(struct device *dev,
resource_size_t start,
resource_size_t n,
const char *name);
void devm_release_mem_region(resource_size_t start, resource_size_t n);

The resource management layer includes a "group" mechanism, accessed viathese functions:

    void *devres_open_group(struct device *dev, void *id, gfp_t gfp);
void devres_close_group(struct device *dev, void *id);
void devres_remove_group(struct device *dev, void *id);
int devres_release_group(struct device *dev, void *id);

A group can be thought of as a marker in the list of allocations associatedwith a given device. Groups are created with devres_open_group(),which can be passed an id value to identify the group orNULL to have the ID generated on the fly; either way, theresulting group ID is returned. A call to devres_close_group()marks the end of a given group. Calling devres_remove_group()causes the system to forget about the given group, but does nothing withthe resources allocated within the group. To remove the group andimmediately free all resources allocated within that group,devres_release_group() should be used.

The group functions seem to be primarily aimed at mid-level code - the buslayers, for example. When bus code tries to attach a driver to a device,for example, it can open a group; should the driver attach fail, the groupcan be used to free up any resources allocated by the driver.

There are not many users of this new API in the kernel now. That maychange over time as driver writers become aware of these functions, and,perhaps, as the list of managed allocation types grows. The reward forswitching over to managed allocations should be more robust and simplercode as current failure and cleanup paths are removed.

(http://lwn.net/Articles/222860/

http://himangi99.wordpress.com/2014/05/16/move-resources-allocated-using-unmanaged-interface-to-managed-devm-interface/

函数 devm_kzalloc()【转】的更多相关文章

  1. Linux中常用的函数

    1.devm_kzalloc() 函数 devm_kzalloc() 和kzalloc()一样都是内核内存分配函数,但是devm_kzalloc()是跟设备(device)有关的,当设备(device ...

  2. Linux i2c子系统(四) _从i2c-s3c24xx.c看i2c控制器驱动的编写

    "./drivers/i2c/busses/i2c-s3c2410.c"是3.14.0内核中三星SoC的i2c控制器驱动程序, 本文试图通过对这个程序的分析, 剥离繁复的细节, 总 ...

  3. Linux内核 kmalloc, kzalloc & devm_kzalloc 区别【转】

    本文转载自:https://blog.csdn.net/u014628531/article/details/50711409 首先,kzalloc()实现了kmalloc()+memset()的功能 ...

  4. devm_kzalloc【转】

    本文转载自:https://blog.csdn.net/liuhuahan/article/details/42145507 看内核代码的时候看到这个函数不理解它的具体作用然后就上网上查,但是网上只查 ...

  5. Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】

    转自:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html 一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道 ...

  6. Python 小而美的函数

    python提供了一些有趣且实用的函数,如any all zip,这些函数能够大幅简化我们得代码,可以更优雅的处理可迭代的对象,同时使用的时候也得注意一些情况   any any(iterable) ...

  7. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  8. JavaScript权威指南 - 函数

    函数本身就是一段JavaScript代码,定义一次但可能被调用任意次.如果函数挂载在一个对象上,作为对象的一个属性,通常这种函数被称作对象的方法.用于初始化一个新创建的对象的函数被称作构造函数. 相对 ...

  9. C++对C的函数拓展

    一,内联函数 1.内联函数的概念 C++中的const常量可以用来代替宏常数的定义,例如:用const int a = 10来替换# define a 10.那么C++中是否有什么解决方案来替代宏代码 ...

随机推荐

  1. Sql按照字段分组,选取其他字段最值所在的行记录

    引言: 为什么会引入这个问题,在程序中遇到这样的问题,在某个数据表中,相同的AID(项目ID)被多次添加到数据表中,所以对应于不同的时间,只想选取添加时间最早的哪一条记录. 参考:红黑联盟 所用到的数 ...

  2. [MVC]View

    /Views/_ViewStart.cshtml 文件会在其他视图文档被加载之前被载入,代码如下: @{ Layout = "~/Views/Shared/_Layout.cshtml&qu ...

  3. PhotoshopCS6

    download: http://www.playnext.cn/photoshop-cs6.html cracker: http://www.playnext.cn/adobe-cs6-crack. ...

  4. scrapy_redis使用介绍

    scrapy_redis是一个基于redis的scrapy组件,通过它可以快速实现简单的分布式爬虫程序,该组件主要提供三大功能: (1)dupefilter——URL去重规则(被调度器使用) (2)s ...

  5. python016 Python3 数据结构

    Python3 数据结构本章节我们主要结合前面所学的知识点来介绍Python数据结构. 列表Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元 ...

  6. NYOJ-613//HDU-1176-免费馅饼,数字三角形的兄弟~~

    免费馅饼 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人 ...

  7. 洛谷P1771 方程的解_NOI导刊2010提高(01)

    题目描述 佳佳碰到了一个难题,请你来帮忙解决. 对于不定方程a1+a2+…+ak-1+ak=g(x),其中k≥2且k∈N,x是正整数,g(x)=x^x mod 1000(即x^x除以1000的余数), ...

  8. visual studio用"查找替换"来删掉源代码中所有//方式的纯注释和空行

    visual studio用"查找替换"来删掉源代码中所有//方式的纯注释和空行 注意:包括/// <summary>这样的XML注释也都删掉了. 步骤1/2(删除注释 ...

  9. centos 6.5 yum安装lnmp

    转自:http://blog.csdn.net/lane_l/article/details/20235909 准备篇: 端口 vi /etc/sysconfig/iptables -A INPUT ...

  10. ST 表学习

    作用:ST算法是用来求解给定区间RMQ的最值,本文以最小值为例 举例: 给出一数组A[0~5] = {5,4,6,10,1,12},则区间[2,5]之间的最值为1. 方法:ST算法分成两部分:离线预处 ...