内存空间

函数列表
| 分配原理 | 最大分配 | 使用情况 | |
| __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); } | |
本文详细介绍了Linux内核中不同类型的内存分配函数,包括kmalloc、kzalloc、__get_free_pages、kmem_cache_alloc、vmalloc、dma_alloc_coherent等,以及它们的适用场景和特点。例如,kmalloc用于分配较小的连续内核逻辑地址内存,而dma_alloc_coherent则确保了DMA操作时的缓存和一致性。同时,文章提到了devm_kzalloc,这是一种与设备关联的内存分配函数,当设备被移除或驱动卸载时,内存会自动释放,防止内存泄漏。

976

被折叠的 条评论
为什么被折叠?



