插件窝 干货文章 Linux进行内存分配的方法步骤

Linux进行内存分配的方法步骤

内存 分配 void size 613    来源:    2025-04-01

在Linux系统中,内存分配主要通过内核机制和用户空间库函数实现。以下是详细的方法步骤和说明:


一、用户空间内存分配方法

1. 使用标准C库函数

#include <stdlib.h>

// 动态分配内存(未初始化)
void *malloc(size_t size);

// 分配并初始化为0
void *calloc(size_t nmemb, size_t size);

// 调整已分配内存大小
void *realloc(void *ptr, size_t size);

// 释放内存
void free(void *ptr);

示例:

int *arr = malloc(10 * sizeof(int));  // 分配10个int的空间
free(arr);  // 释放内存

2. 对齐内存分配

#include <stdlib.h>
void *aligned_alloc(size_t alignment, size_t size);  // C11标准
posix_memalign(void **memptr, size_t alignment, size_t size);  // POSIX标准

3. 共享内存分配

#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);

示例:

void *mem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
munmap(mem, 4096);  // 释放

二、内核空间内存分配方法

1. 通用内存分配(kmalloc/kfree)

#include <linux/slab.h>
void *kmalloc(size_t size, gfp_t flags);  // 分配物理连续的内存
void kfree(const void *objp);

常用flags - GFP_KERNEL:普通优先级,可能触发回收。 - GFP_ATOMIC:原子分配,禁止休眠。

2. 页分配器(alloc_pages)

#include <linux/gfp.h>
struct page *alloc_pages(gfp_t gfp_mask, unsigned int order);  // 分配2^order个连续页
void *page_address(struct page *page);  // 获取页的虚拟地址

3. SLAB分配器(专用缓存)

kmem_cache_create()  // 创建专用缓存
kmem_cache_alloc()   // 从缓存分配
kmem_cache_free()    // 释放到缓存

4. vmalloc(虚拟连续但物理不连续)

#include <linux/vmalloc.h>
void *vmalloc(unsigned long size);
void vfree(const void *addr);

三、高级内存管理技巧

  1. 内存池(Memory Pool)

    • 预分配内存块减少碎片(如使用mempool)。
  2. OOM(Out-of-Memory)处理

    • 通过/proc/sys/vm/overcommit_memory调整策略:
      • 0:启发式overcommit(默认)
      • 1:总是overcommit
      • 2:禁止overcommit
  3. 透明大页(THP)

    • 启用:echo always > /sys/kernel/mm/transparent_hugepage/enabled

四、调试与监控工具

  1. 查看内存使用

    free -h        # 查看系统内存
    vmstat 1       # 监控内存和交换
    cat /proc/meminfo  # 详细内存信息
    
  2. 检测内存泄漏

    • 用户空间:valgrind --leak-check=yes ./program
    • 内核空间:kmemleak工具
  3. 手动释放缓存

    sync; echo 3 > /proc/sys/vm/drop_caches  # 释放PageCache/Slab
    

五、注意事项

  1. 用户空间分配失败时:检查errno(如ENOMEM)。
  2. 内核空间分配失败:可能导致NULL或触发OOM Killer。
  3. 性能权衡
    • kmalloc(物理连续) vs vmalloc(虚拟连续)
    • GFP_KERNEL(可休眠) vs GFP_ATOMIC(原子操作)

通过合理选择分配方法,可以优化性能和资源利用率。