内存管理篇-14kmalloc机制实现分析

        引入这个kmalloc的目的,是因为前面的slab接口太过于复杂,因此需要一个全新的封装kmalloc接口,内存申请编程接口实现。kmalloc底层起始也是基于slab缓存实现的

1.kmalloc 调用流程

  1. 参数解析: 解析 gfp_mask 参数,确定分配时是否可以睡眠、是否需要零初始化等。解析 size 参数,确定要分配的内存大小。
  2. 查找缓存:(1)根据请求的大小 size 查找合适的缓存。(2)如果找不到合适的缓存,则可能需要创建一个新的缓存。
  3. 分配对象:(1)从找到的缓存中分配一个对象 (2)如果缓存中的对象不足,则可能需要创建一个新的 slab。(3)如果需要,初始化分配的内存为零。
  4. 返回结果: 返回指向分配的内存块的指针。

 大概实现方式示例

#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/kmalloc.h>
void *kmalloc(size_t size, gfp_t gfp_mask)
{
    struct kmem_cache *cache;
    void *ptr;

    // Find the appropriate cache
    cache = find_kmem_cache(size);

    // Allocate from the cache
    ptr = kmem_cache_alloc(cache, gfp_mask);

    // Initialize memory if required
    if (gfp_mask & __GFP_ZERO)
        memset(ptr, 0, size);

    return ptr;
}

static struct kmem_cache *find_kmem_cache(size_t size)
{
    return kmem_cache_find(size);
}

 2.函数的实践

 3.实现源码解析

        总结下来就是说,kmalloc函数最终调用的是kmem_cache和伙伴系统来实现的,它比kmem_cache那套函数接口实现要简单很多。

当申请的内存大于8KB的时候:        

        如果不是slob,并且大小于8KB,然后去获取索引:index = kmalloc_index(size)。接下来就通过kmem_alloc_trace申请内存。上节说到slab通过一些列的kmem_cache链表连接组成,获取索引(实际上就是order)之后需要找到对应的kmem_cache,kmem_cache_alloc_trace函数根据前面的索引,再到对应的slab上获取对应的内存。

        kmem_cache_alloc_trace函数需要的参数就比较明显了:(1)需要知道是哪个kmem_cache,大小,和flags。然后内部又有slab_alloc进行封装。

        slab_alloc最终的申请过程包括:(1)this_cpu_read函数到对应的CPU缓存区申请。这里其实也挺复杂的,没有想象中那么简单。

 

遗留问题:

kmalloc能申请的最大块的连续内存是多少?

  • 由于kmalloc最终是通过slab或者伙伴系统中获取的内存,所以最大的内存就是pageblock的大小(4MB和max_order的配置有关)。

kmalloc返回的地址已对齐方式?

  • slab的接口支持配置对齐方式,前面的kmem_cache_create函数有这个参数

kmalloc返回的是虚拟地址还是物理地址?

  • 不管是slab或者伙伴系统内存申请,最终都会通过page_to_virt进行转换虚拟地址。在 Linux 内核中,kmalloc 是用于分配内核空间中的小块内存的函数。它返回的指针是指向内核虚拟地址空间中的内存区域。这是因为现代计算机系统普遍使用虚拟内存机制,内核和用户空间的内存访问都是通过虚拟地址进行的。当你调用 kmalloc 时,它会根据你请求的大小查找或创建一个合适的缓存,并从这个缓存中分配一个对象。这个对象的地址是内核虚拟地址空间中的地址。因此,当你使用 kmalloc 分配的内存时,你是在操作虚拟地址。
  • kmem_cache_alloc 函数返回的是虚拟地址。
  • 在 Linux 内核中,struct page 结构体代表一个物理页帧,并包含了关于该页帧的一些元数据。alloc_pages 函数用于分配物理页帧,并返回一个指向这些页帧的 struct page 结构体数组的指针。但是所有的内存申请,最终会在某个阶段通过page_to_virt转换成虚拟地址

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LuckyDog0623

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值