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

news2024/9/24 21:22:11

        引入这个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.coloradmin.cn/o/2084212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构与算法学习day18-层序遍历

层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。需要借用一个辅助数据结构即队列来实现&#xff0c;队列先进先出&#xff0c;符合一层一层遍历的逻辑&#xff0c;而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。…

硬盘崩溃数据无踪?Windows数据恢复TOP4揭秘,2024年助你找回宝贵资料

现在我们的生活、工作、学习都离不开电脑&#xff0c;电脑里的硬盘就像个装满宝贝的箱子&#xff0c;里面全是我们宝贵的照片、文档、视频和美好回忆。但要是硬盘突然坏了&#xff0c;东西一下子全没了&#xff0c;那感觉真是太糟糕了。别担心&#xff0c;今天我们就给你介绍几…

2024年中国运筹学会运筹竞赛(数据驱动赛道)报名通知

竞赛组织 主办单位&#xff1a;中国运筹学会&#xff08;国家一级学会&#xff09; 承办单位&#xff1a;中国科学技术大学 支持单位&#xff1a;杉数科技、海康威视、中国科学技术大学管理学院、《运筹学学报》杂志 竞赛内容 本次竞赛&#xff08;本科生组&#xff09;由竞…

不平衡数据集的单类分类算法

不平衡数据集的单类分类算法 异常值或异常是与其他数据不符的罕见例子。 识别数据中的离群值称为离群值或异常检测&#xff0c;机器学习中专注于此问题的子领域称为单类分类。这些是无监督学习算法&#xff0c;旨在对“正常”示例进行建模&#xff0c;以便将新示例分类为正常…

记录一次给iOS 工程添加.gitignore文件

新建了一个iOS工程&#xff0c;修改过代码之后&#xff0c;提交发现有一些自己不想要提交的内容 如下图&#xff0c;里面有.DS_Store文件&#xff0c;还有xcsuserstate文件&#xff0c; 这个时候需要添加忽略文件 首先在工程文件夹中执行 touch .gitignore 创建忽略文件&#…

Unity2D游戏开发-Pak木鱼

在接下来文章里我会以Unity为主一起制作游戏 在unity 里如何制作一个简单的敲木鱼游戏&#xff1f; 创建一个2D场景&#xff08;本人使用Unity2023&#xff09; (每个一段时间要申请一个个人许可证) 点击下方蓝色按钮创建 将以下素材拖动到Assets文件夹中 这张图随意命名我…

Swift concurrency 4 — Task和.task的理解与使用

Task Swift中的Task是一种异步操作&#xff0c;它提供了一种替代DispatchQueue.main.async{}等传统方法的方法。通过使用Task&#xff0c;我们可以简化代码并更好地控制异步操作。此外&#xff0c;Task还提供了其他选项&#xff0c;可以进一步增强任务执行。 先看一个Task的基…

net core中byte数组如何高效转换为16进制字符串

在 .NET Core 中&#xff0c;如何把 byte[] 转换为 16 进制字符串&#xff1f;你能想到哪些方法&#xff1f;什么方式性能最好&#xff1f;今天和大家分享几种转换方式。 往往在处理字符串性能问题时&#xff0c;首先应该想到的是怎么想办法减少内存分配&#xff0c;怎么优化字…

22.优化器

优化器 当使用损失函数时&#xff0c;可以调用损失函数的 backward&#xff0c;得到反向传播&#xff0c;反向传播可以求出每个需要调节的参数对应的梯度&#xff0c;有了梯度就可以利用优化器&#xff0c;优化器根据梯度对参数进行调整&#xff0c;以达到整体误差降低的目的。…

Cryptomator:开源云存储加密

采用最新技术标准&#xff0c;提供最佳保护 如果有人查看您云中的文件夹&#xff0c;他们无法对您的数据得出任何结论。 Cryptomator 提供开源的客户端云文件加密。 它适用于 Windows、Linux、macOS 和 iOS。 Cryptomator 可与 Dropbox、Google Drive、OneDrive、MEGA、pClo…

【QT | 开发环境搭建】Linux系统(Ubuntu 18.04) 安装 QT 5.12.12 开发环境

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 2024-08-29 …

C# 委托详解(Delegate)

引言 在 C# 编程当中&#xff0c;委托&#xff08;Delegate&#xff09;是一种特殊的类型&#xff0c;它允许将方法作为参数传递给其他方法&#xff0c;或者将方法作为返回值返回&#xff0c;这种特性使得委托成为实现回调函数、事件处理等&#xff0c;所有的委托都派生自Syst…

【STM32开发笔记】使用RT-Thread的SDIO驱动和FATFS实现SD卡文件读写

【STM32开发笔记】使用RT-Thread的SDIO驱动和FATFS实现SD卡文件读写 一、准备工作1.1 准备好开发板和SD卡1.2 创建RT-Thread项目 二、配置RT-Thread2.1 打开文件系统相关配置2.2 打开SD卡相关配置2.3 打开RTC配置2.4 重新生成Keil项目文件 三、编译、烧录、运行3.1 编译项目3.2…

网站建设完成后, 营销型网站如何做seo

营销型网站的SEO优化旨在提高网站在搜索引擎中的排名&#xff0c;从而吸引更多潜在客户并促进销售。以下是营销型网站SEO的详细解析&#xff1a; 关键词研究与优化 目标受众分析&#xff1a;了解目标受众的搜索习惯和需求&#xff0c;确定适合的关键词。使用工具来发现相关关键…

RV1126的GPIO计算和使用

1、获取GPIO芯片对应的序号值 先读取下/sys/kernel/debug/gpio的值&#xff0c;得到每个GPIO芯片的序号范围&#xff0c;如GPIO芯片0就为0~31。 2、根据GPIO硬件编号计算出系统内使用的GPIO序号 根据GPIO的编号&#xff0c;比如说GPIO3_B0&#xff0c;前面GPIO3代表看GPIO3的信…

傻瓜操作:GraphRAG、Ollama 本地部署及踩坑记录

目录 一、GraphRAG 介绍1.引言2.创新点3. 算法4. 数据和实验结果5.不足和展望 二、本地部署1.为什么要本地部署2.环境准备3. GraphRAG 安装3.1 下载 GraphGAG3.2 安装依赖包3.3 创建数据目录3.4 项目初始化3.5 修改配置文件 3.6 修改.env文件3.7 修改源码 4. Indexing5. query5…

Linux关于压缩之后文件更大的解释

记录于24年八月29 使用vim命令创建了lianxi1和lianxi2并在里面填写了一些内容&#xff0c;发现使用gzip和zip压缩后文件反而更大 事后问了一下ai回答了我的疑惑 压缩算法开销&#xff1a;如前所述&#xff0c;压缩文件需要存储额外的元数据和文件结构信息。这种开销在处理非常…

C++ TinyWebServer项目总结(13. 多进程编程)

本章讨论Linux多进程编程的以下内容&#xff1a; 复制进程映像的fork系统调用和替换进程映像的exec系列系统调用。僵尸进程以及如何避免僵尸进程。进程间通信&#xff08;Inter Process Communication&#xff0c;IPC&#xff09;最简单的方式&#xff1a;管道。三种System V进…

浏览器插件利器--allWebPluginV2.0.0.18-alpha版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…

[MRCTF2020]Unravel!!

使用zsteg查看图片有隐藏文件&#xff0c;没有头绪&#xff0c;先放弃 使用zsteg和010editor查看都发现一个png图片 把JM.png拷贝到kali&#xff0c;使用binwalk分离&#xff0c;得到一个aes.png 使用010editor查看wav&#xff0c;发现尾部有可疑的字符串&#xff0c;拷贝出来备…