linux内核的内存分配函数

内存空间

内存分配

 函数列表

分配原理

最大分配

使用情况

__get_free_pages

直接对页框进行操作

4MB

适用于分配较大量的连续物理内存

kmem_cache_alloc

基于slab机制实现

128KB

适合需要频繁申请释放相同大小内存块

kmalloc

基于kmem_cache_alloc实现

128KB

(include/lin

ux/Kmalloc_si

ze.h的内容决定

较常用,分配的地址称为内核逻辑地址。物理地址和逻辑地址都连续。分配的内存处于3GB~high_memory之间,这段内核空间与物理内存的映射一一对应

需要小于页框大小的内存。

不对获得的空间清零,需要自己调用memset清零

kzalloc

基于kmalloc实现

128KB

和kmalloc基本相同。此函数分配的空间初始化为0

vmalloc

建立非连续物理内存到虚拟地址的映射

分配的地址称为内核虚拟地址。

虚拟地址连续,物理内存不连续

分配的内存在 VMALLOC_START~4GB之间

适合需要大内存,但是对地址连续性没有要求的场合

比kmalloc慢

dma_alloc_writecombine

或dma_alloc_coherent

基于__alloc_pages实现

4MB

适用于DMA操作

返回值:虚拟地址

第三个参数:申请到的物理地址

ioremap

实现已知物理地址到虚拟地址的映射

适用于物理地址已知的场合,如设备驱动

alloc_bootmem

在启动kernel时,预留一段内存,内核看不见

小于物理内存大小,内存管理要求较高

kmalloc

简介

用kfee()来释放

原型

void *kmalloc(size_t size, int flags);

参数

size:要分配的块的大小

flags:分配标志,常用GFP_KERNEL;

GFP前缀的由来: 调用get_free_pages来实现实际的分配。见《Linux内核设计与实现》 => 第12章 内存管理

返回值

成功返回分配的目标内存空间的首地址;          失败返回NULL.   

 __get_free_pages

简介

(用free_pages()来释放)

原型

unsigned long __get_free_pages(gfp_t gfp_k, unsigned int order)

参数

gfp_k:分配标志(flags),常用GFP_KERNEL

order:分配的指数:实际大小是2^order,可以用order = ger_order(size)  来获得。     //size代表实际大小

返回值

成功返回分配的目标内存空间的首地址;          失败返回NULL.   

devm_kzalloc

详细讲解见:Linux设备模型(9)_device resource management

作用

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

当设备(device)被detached或者驱动(driver)卸载(unloaded)时,内存会被自动释放。另外,也可以通过函数

devm_kfree()手动释放。

    而kzalloc()则需要手动释放(使用kfree()),但如果工程师检查不仔细,则有可能造成内存泄漏。

格式

static inline void * devm_kzalloc(struct device * dev,size_t size,gfp_t gfp)

{undefined

    return devm_kmalloc(dev,size,gfp | __GFP_ZERO);                                                                                                                                                         

}

void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)                                                                                                                                               

{undefined

    struct devres *dr;

     

    dr = alloc_dr(devm_kmalloc_release, size, gfp, dev_to_node(dev));

    if (unlikely(!dr))

        return NULL;

    set_node_dbginfo(&dr->node, "devm_kzalloc_release", size);

    devres_add(dev, dr->data);

    return dr->data;

}

EXPORT_SYMBOL_GPL(devm_kmalloc);

void devm_kfree(struct device * dev,void * p)                                                                                                                                                                  

{undefined

    int rc;

    rc = devres_destroy(dev,devm_kmalloc_release,devm_kmalloc_match,p);

    WARN_ON(RC);

}

EXPORT_SYMBOL_GPL(devm_kfree);

示例

struct s3c2440_i2c_dev {undefined

  struct device *dev;

  void __iomem *base;

  struct i2c_msg *msg;

  u32  frequency;

  int speed_mode;

  int slave_addr;

  struct i2c_adapter  adap;

};

static int s3c2440_i2c_probe(struct platform_device *pdev)

{undefined

  struct s3c2440_i2c_dev *i2c_dev;

  struct i2c_adapter *adap;

  struct device *dev = &pdev->dev;

  struct resource *res;

  i2c_dev = devm_kzalloc(&pdev->dev, sizeof(struct s3c2440_i2c_dev), GFP_KERNEL);

  if(!i2c_dev)

  return -ENOMEM;

  ...

}

dma_alloc_coherent

简介

申请DMA区域的内存,保证此段内存是cache和dma的一致性问题。

详见:《Linux设备驱动开发详解:基于最新的Linux4.0内核》=>

   11.6.1 DMA与cache一致性

注意:目前没有devm_dma_alloc_coherent

原型

static inline void *dma_alloc_coherent(struct device *dev, size_t size,

dma_addr_t *dma_handle, gfp_t flag)

dev : struct device指针,可以平台初始化里指定,主要是dma_mask之类,可参考framebuffer。

一般在probe函数中,

static int hik_fmc_probe(struct platform_device *pdev)

  struct device *dev = &pdev->dev

size :实际分配大小

dma_handle:返回的内存物理地址,供dma使用

flag: gfp标记。如GFP_KERNEL

返回值:内存虚拟地址。

一般把handle值写到控制器寄存器上,内核可以直接操作返回值(虚拟地址)

对应的释放函数:

dma_free_coherent(dev, 4096+256, vir_buf, dma_handle);

示例

static int s3c2440_fmc_probe(struct platform_device *pdev)

{undefined

    struct device *dev = &pdev->dev;

    dma_addr_t dma_handle;

    char *vir_buf;

    vir_buf = dma_alloc_coherent(dev, 4096+256, &dma_handle, GFP_KERNEL);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值