内存空间
函数列表
分配原理 | 最大分配 | 使用情况 | |
__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) { return devm_kmalloc(dev,size,gfp | __GFP_ZERO); } void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) { 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) { 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 { 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) { 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) { 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); } |