当前位置: 首页 > article >正文

内存管理篇-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转换成虚拟地址

 


http://www.kler.cn/a/287446.html

相关文章:

  • Linux:调试器-gdb/cgdb
  • delphi fmx android 离线人脸识别
  • Mac os 系统上如何开启远程登录的 ssh 22 端口
  • prop校验,prop和data区别
  • 跨平台WPF框架Avalonia教程 一
  • C指针之舞——指针探秘之旅
  • SpringBoot整合积木报表
  • 14 大模型微调-KitTrain
  • OpenGL/GLUT实践:绘制旋转的立方体与雪人世界——添加光照与SOIL方式添加纹理(电子科技大学信软图形与动画Ⅱ实验)
  • Linux中如何查看一个进程?如何杀死一个进程?如何查看某个端口有没有被占用?
  • 【Python报错已解决】`TypeError: ‘numpy.ndarray‘ object is not callable`
  • DDS(Data Distribution Service)的数据状态分布和管理简单介绍
  • 微软AD替代方案统一管理Windows和信创电脑的登录认证与网络准入认证
  • Redis的内存淘汰策略- allkeys-lru
  • 用相图分析 bbr,inflight 守恒的收敛速度
  • HTTP协议的建立和终止涉及到TCP协议的连接管理
  • 网络:通过ipv6打开网页
  • 打脸预测,AI泡沫破裂,科技衰退
  • Go语言的编程规则和秘籍
  • 第十三节:学习Springboot整合mybatis——完整篇(自学Spring boot 3.x的第三天)
  • 电脑从按电源键开始到系统启动的全过程
  • Mybatis-plus拦截器BaseMultiTableInnerInterceptor实现(使用场景)
  • 秋招/春招投递公司记录表格
  • 公司来了个大佬,把FullGC 40次/天优化为10天1次,太秀了~!
  • 每天学习一个基础算法之二分查找
  • Python 生成随机的国内 ip