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

news/2024/9/23 7:28:19/

        引入这个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 cachecache = find_kmem_cache(size);// Allocate from the cacheptr = kmem_cache_alloc(cache, gfp_mask);// Initialize memory if requiredif (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.ppmy.cn/news/1517299.html

相关文章

2024117读书笔记|《李煜词(果麦经典)》——一壶酒,一竿身,快活如侬有几人?一片芳心千万绪,人间没个安排处

2024117读书笔记|《李煜词&#xff08;果麦经典&#xff09;》——一壶酒&#xff0c;一竿身&#xff0c;快活如侬有几人&#xff1f;一片芳心千万绪&#xff0c;人间没个安排处 《李煜词&#xff08;果麦经典&#xff09;》李煜的词很美&#xff0c;插图也不错&#xff0c;很值…

25届应届网安面试,默认页面信息泄露

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

模拟实现STL中的unordered_map和unordered_set

目录 1.unordered_map和unordered_set简介 2.unordered_map和unordered_set设计图 3.迭代器的设计 4.哈希表的设计 5.my_unordered_map和my_unordered_set代码 1.unordered_map和unordered_set简介 unordered_map和unordered_set的使用非常类似于map和set&#xff0c;两…

GATK ReadsPathDataSource类介绍

GATK&#xff08;Genome Analysis Toolkit&#xff09;是一个广泛使用的基因组分析工具包&#xff0c;它的核心库之一是htsjdk&#xff0c;用于处理高通量测序数据。在GATK中&#xff0c;ReadsPathDataSource类是负责管理和提供读取高通量测序数据文件&#xff08;如BAM、SAM、…

android selinux报avc denied权限和编译报neverallow解决方案

avc: denied { read } for name“present” dev“sysfs” ino42693 scontextu:r:hal_health_default:s0 tcontextu:object_r:sysfs:s0 tclassfile permissive1 denied {xxx}: 表示缺少什么权限 scontext:表示谁缺少权限 tcontext:表示对那些文件缺少权限&#xff1a; tclass&am…

华为云 x 容联云|828企业节,助推中国数智产业实力再升级

2024年8月27日&#xff0c;华为第三届828 B2B企业节在2024中国国际大数据产业博览会上正式开幕。 828 B2B企业节是全国首个基于数字化赋能的企业节&#xff0c;由华为联合上万家生态伙伴共同发起&#xff0c;旨在为广大企业尤其是中小企业搭建数字化创新发展平台&#xff0c;融…

关于Arrays.asList返回List无法新增和删除?

这个是在写项目的时候发现的&#xff0c;然后就分析了一下源码&#xff0c;得其内部原理 复现代码示例&#xff1a; public class ArraysAsList {public static void main(String[] args) {Integer[] array {1, 2, 3, 4, 5};List<Integer> list Arrays.asList(array);…

网络通信tcp

管道通信与数据复制管道通信确实涉及数据复制的过程&#xff0c;这是由于管道的工作原理所决定的。下面详细解释一下&#xff1a;管道通信的数据复制 1. 写入管道&#xff1a;•当一个进程通过 write() 系统调用向管道写入数据时&#xff0c;数据实际上是从进程的用户空间复制…