插件窝 干货文章 [务必收藏] Linux用户空间和内核空间所有15种内存分配方法总结

[务必收藏] Linux用户空间和内核空间所有15种内存分配方法总结

分配 内存 void size 650    来源:    2025-05-12

Linux用户空间和内核空间内存分配方法总结

用户空间内存分配方法

1. malloc/free

#include <stdlib.h>
void *malloc(size_t size);
void free(void *ptr);
  • 标准C库提供的动态内存分配函数
  • 分配在堆(heap)上
  • 分配的内存未初始化,可能包含随机数据

2. calloc

#include <stdlib.h>
void *calloc(size_t nmemb, size_t size);
  • 分配并清零内存
  • 适合数组分配,计算总大小为 nmemb × size

3. realloc

#include <stdlib.h>
void *realloc(void *ptr, size_t size);
  • 调整已分配内存块的大小
  • 可能移动内存位置,返回新指针

4. alloca

#include <alloca.h>
void *alloca(size_t size);
  • 在栈(stack)上分配内存
  • 函数返回时自动释放
  • 不推荐使用,可能导致栈溢出

5. mmap/munmap

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);
  • 内存映射文件或设备
  • 可用于大内存分配,绕过堆管理器
  • 支持多种标志:MAP_ANONYMOUS(匿名映射), MAP_PRIVATE/MAP_SHARED等

6. brk/sbrk

#include <unistd.h>
int brk(void *addr);
void *sbrk(intptr_t increment);
  • 直接调整程序断点(program break)
  • 主要用于实现malloc等函数
  • 现代程序一般不直接使用

7. posix_memalign

#include <stdlib.h>
int posix_memalign(void **memptr, size_t alignment, size_t size);
  • 分配对齐的内存
  • 对齐值必须是2的幂次方且是sizeof(void*)的倍数

8. memalign/valloc

#include <malloc.h>
void *memalign(size_t alignment, size_t size);
void *valloc(size_t size);
  • 旧版对齐内存分配函数
  • valloc分配页面对齐的内存

内核空间内存分配方法

9. kmalloc/kfree

#include <linux/slab.h>
void *kmalloc(size_t size, gfp_t flags);
void kfree(const void *objp);
  • 内核中最常用的分配器
  • 分配物理连续的内存
  • 使用GFP标志控制分配行为(GFP_KERNEL, GFP_ATOMIC等)

10. vmalloc/vfree

#include <linux/vmalloc.h>
void *vmalloc(unsigned long size);
void vfree(const void *addr);
  • 分配虚拟地址连续但物理地址不一定连续的内存
  • 适合大内存分配
  • 性能略低于kmalloc

11. alloc_pages/free_pages

#include <linux/gfp.h>
struct page *alloc_pages(gfp_t gfp_mask, unsigned int order);
void free_pages(unsigned long addr, unsigned int order);
  • 按页分配内存
  • order参数指定分配2^order个连续页
  • 返回page结构指针或虚拟地址

12. get_free_page/free_page

#include <linux/gfp.h>
unsigned long get_zeroed_page(gfp_t gfp_mask);
unsigned long __get_free_page(gfp_t gfp_mask);
unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
void free_page(unsigned long addr);
void free_pages(unsigned long addr, unsigned int order);
  • 分配一个或多个连续页
  • get_zeroed_page返回已清零的页
  • 返回虚拟地址

13. slab分配器(kmem_cache)

#include <linux/slab.h>
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,
                    unsigned long flags, void (*ctor)(void *));
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags);
void kmem_cache_free(struct kmem_cache *cachep, void *objp);
void kmem_cache_destroy(struct kmem_cache *cachep);
  • 为频繁分配/释放的相同大小对象设计
  • 减少内存碎片和提高性能
  • 内核中许多数据结构使用此机制

14. kzalloc

#include <linux/slab.h>
void *kzalloc(size_t size, gfp_t flags);
  • kmalloc的变体,分配后自动清零内存
  • 相当于用户空间的calloc

15. devm_kmalloc (设备资源管理)

#include <linux/device.h>
void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp);
  • 设备驱动中使用的资源管理分配器
  • 分配的内存与设备关联,设备卸载时自动释放

选择建议

用户空间: - 一般用途:malloc/calloc/realloc - 需要对齐:posix_memalign - 大内存或特殊需求:mmap

内核空间: - 小内存(通常<1页):kmalloc/kzalloc - 大内存:vmalloc - 频繁分配释放的固定大小对象:slab分配器 - 页级分配:alloc_pages/get_free_pages - 设备驱动:devm_kmalloc

理解这些内存分配方法的区别和适用场景对于开发高效、稳定的Linux应用程序和内核模块至关重要。