Linux内核内存分配机制说明

在Linux内核中,mallockmalloc是用于内存分配的函数,但它们分别用于用户空间和内核空间,且实现机制不同。

1. malloc(用户空间内存分配)

malloc是C标准库中的函数,用于在用户空间分配内存。它通常通过brkmmap系统调用来实现。

分配机制

  • brk系统调用malloc通过调整堆的顶部(brk指针)来分配内存。堆是一个连续的内存区域,brk指针指向堆的顶部。当malloc需要分配内存时,它会调用brk系统调用来扩展堆的大小。
  • mmap系统调用:对于较大的内存分配,malloc可能会使用mmap系统调用,将文件或匿名内存映射到进程的地址空间。mmap分配的内存不依赖于堆,且可以独立释放。

源码分析

malloc的实现通常在C标准库(如glibc)中,而不是内核源码中。以下是一个简化的malloc实现逻辑:

void* malloc(size_t size) {
    if (size <= 0) return NULL;

    // 使用brk或mmap分配内存
    void* ptr = sbrk(size);
    if (ptr == (void*)-1) {
        // 如果brk失败,尝试使用mmap
        ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        if (ptr == MAP_FAILED) {
            return NULL;
        }
    }
    return ptr;
}

2. kmalloc(内核空间内存分配)

kmalloc是Linux内核中用于分配小块内存的函数。它使用内核的SLAB分配器或SLUB分配器来管理内存。

分配机制

  • SLAB/SLUB分配器kmalloc依赖于SLAB或SLUB分配器来管理内核内存。SLAB分配器将内存划分为多个大小不同的缓存(cache),每个缓存用于分配特定大小的内存块。SLUB是SLAB的改进版本,提供了更好的性能和更简单的实现。
  • 内存分配时机:当调用kmalloc时,内核会从适当的缓存中分配一个内存块。如果缓存中没有可用的内存块,内核会从伙伴系统(Buddy System)中分配一个页面,并将其分割成适当大小的块。

源码分析

kmalloc的实现位于内核源码的slab.cslub.c中。以下是一个简化的kmalloc实现逻辑:

void* kmalloc(size_t size, gfp_t flags) {
    struct kmem_cache *cache;
    void *object;

    // 根据大小选择合适的缓存
    cache = kmalloc_slab(size, flags);
    if (unlikely(ZERO_OR_NULL_PTR(cache)))
        return cache;

    // 从缓存中分配对象
    object = slab_alloc(cache, flags, _RET_IP_);
    return object;
}

  • kmalloc_slab:根据请求的大小选择合适的SLAB缓存。
  • slab_alloc:从选定的缓存中分配一个内存块。

3. 内存分配的真正时机

  • 用户空间(malloc:当malloc调用brkmmap时,内核会更新进程的内存映射,并分配物理内存。物理内存的分配可能延迟到实际访问内存时(即“按需分页”机制)。
  • 内核空间(kmalloc:当kmalloc调用时,内核会立即从SLAB/SLUB缓存中分配内存。如果缓存中没有可用内存,内核会从伙伴系统中分配页面,并将其添加到缓存中。

4. 总结

  • malloc:用于用户空间,通过brkmmap系统调用分配内存,物理内存的分配可能延迟到实际访问时。
  • kmalloc:用于内核空间,通过SLAB/SLUB分配器分配内存,物理内存的分配是立即进行的。

两者都依赖于内核的内存管理机制,但malloc在用户空间运行,而kmalloc在内核空间运行。

你可能感兴趣的:(开发语言,linux,objective-c)