14 内核开发-slab 子系统,kmalloc、kzalloc 和 kfree

2024-04-28 22:20

本文主要是介绍14 内核开发-slab 子系统,kmalloc、kzalloc 和 kfree,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

14 内核开发-slab 子系统,kmalloc、kzalloc 和 kfree

目录

14 内核开发-slab 子系统,kmalloc、kzalloc 和 kfree

1.定义

2.内涵

3.使用示例

4.具体代码使用实践

5.注意事项

6.最佳实践

7.总结



课程简介:
Linux内核开发入门是一门旨在帮助学习者从最基本的知识开始学习Linux内核开发的入门课程。该课程旨在为对Linux内核开发感兴趣的初学者提供一个扎实的基础,让他们能够理解和参与到Linux内核的开发过程中。

课程特点
1. 入门级别:该课程专注于为初学者提供Linux内核开发的入门知识。无论你是否具有编程或操作系统的背景,该课程都将从最基本的概念和技术开始,逐步引导学习者深入了解Linux内核开发的核心原理。

2. 系统化学习:课程内容经过系统化的安排,涵盖了Linux内核的基础知识、内核模块编程、设备驱动程序开发等关键主题。学习者将逐步了解Linux内核的结构、功能和工作原理,并学习如何编写和调试内核模块和设备驱动程序。

3. 实践导向:该课程强调实践,通过丰富的实例和编程练习,帮助学习者将理论知识应用到实际的Linux内核开发中。学习者将有机会编写简单的内核模块和设备驱动程序,并通过实际的测试和调试来加深对Linux内核开发的理解。

4. 配套资源:为了帮助学习者更好地掌握课程内容,该课程提供了丰富的配套资源,包括教学文档、示例代码、实验指导和参考资料等。学习者可以根据自己的学习进度和需求,灵活地利用这些资源进行学习和实践。

无论你是计算机科学专业的学生、软件工程师还是对Linux内核开发感兴趣的爱好者,Linux内核开发入门课程都将为你提供一个扎实的学习平台,帮助你掌握Linux内核开发的基础知识,为进一步深入研究和应用Linux内核打下坚实的基础。

这一讲,主要分享如何在内核开模块开发中如何使用slab 子系统,kmalloc、kzalloc 和 kfree
来进行内存管理分配回收。


1.定义


slab、kmalloc、kzalloc 和 kfree 在 Linux 内核中都用于管理内存分配,但它们之间存在一些关键差异:

  • slab 是一个子系统,用于管理内核对象(如文件系统inode 和套接字缓冲区)的内存分配。它使用一种称为 slab 缓存的机制来减少内存碎片并提高分配和释放性能。
  • kmalloc 和 kzalloc 是函数,用于从内核堆中分配内存。kmalloc 分配的内存未初始化,而 kzalloc 分配的内存被清零。

kfree 是一个函数,用于释放先前由 kmalloc 或 kzalloc 分配的内存。
slab 与 kmalloc/kzalloc/kfree 的关系,slab 子系统与 kmalloc、kzalloc 和 kfree 函数一起工作,如下所示:

  • kmalloc 和 kzalloc 函数用于从 slab 缓存中分配对象。
  • kfree 函数用于将对象释放回 slab 缓存。

通过使用 slab 子系统,kmalloc、kzalloc 和 kfree 函数可以高效且可扩展地分配和释放内核对象内存。


2.内涵


何时使用 slab,何时使用kmalloc kzalloc ?这里提供一个简单的原则,可以参考:

应在以下情况下使用 slab 子系统:

  • 当需要为内核对象分配大量内存时。
  • 当需要高效地分配和释放内核对象时。
  • 当需要减少内存碎片时。
  • 何时使用 kmalloc/kzalloc/kfree

应在以下情况下使用 kmalloc 和 kzalloc 函数:

  • 当需要为非内核对象分配内存时。
  • 当不需要高效的内存分配和释放时。
  • 当不需要减少内存碎片时。
3.使用示例

kmalloc/kzalloc/kfree

(a)kmalloc

void kmalloc(size_t size, gfp_t flags);
其中:size:要分配的内存大小(以字节为单位)。flags:指定分配标志的标志。GFP_KERNEL:这是一个分配标志,它指示内核应从内核内存池中分配内存。GFP_KERNEL 标志是最常用的标志,它适用于大多数内核内存分配。函数的运作方式:当调用 kmalloc(1024, GFP_KERNEL); 时,内核将执行以下操作:它将在内核内存池中搜索一个大小至少为 1024 字节的空闲内存块。
如果找到一个合适的块,内核将分配该块并将其返回给调用者。
如果找不到合适的块,内核将尝试从伙伴系统中分配一个新块。伙伴系统是一种内存管理技术,它将内存划分为不同大小的块,以便有效分配和释放内存。
如果伙伴系统无法分配一个新块,内核将返回 NULL,表示分配失败。

(b)kzalloc

void kzalloc(size_t size, gfp_t flags);其中:size:要分配的内存大小(以字节为单位)。flags:指定分配标志的标志。
sizeof(struct myctx):这是要分配的内存大小,以字节为单位。在本例中,它分配一个足够大以容纳 struct myctx 结构体的内存块。GFP_KERNEL:这是一个分配标志,它指示内核应从内核内存池中分配内存。GFP_KERNEL 标志是最常用的标志,它适用于大多数内核内存分配。函数的运作方式:当调用 kzalloc(sizeof(struct myctx), GFP_KERNEL); 时,内核将执行以下操作:它将在内核内存池中搜索一个大小至少为 sizeof(struct myctx) 字节的空闲内存块。
如果找到一个合适的块,内核将分配该块,并将其初始化为零。然后,它将块返回给调用者。
如果找不到合适的块,内核将尝试从伙伴系统中分配一个新块。伙伴系统是一种内存管理技术,它将内存划分为不同大小的块,以便有效分配和释放内存。
如果伙伴系统无法分配一个新块,内核将返回 NULL,表示分配失败。

(c)kfree

void kfree(const void ptr);ptr:要释放的内存块的地址。函数的运作方式:当调用 kfree(ctx); 时,内核将执行以下操作:它将检查 ctx 是否为 NULL。如果是,函数将立即返回,没有任何操作。
内核将检查 ctx 指向的内存块是否由 kmalloc() 或 kzalloc() 分配。如果不是,函数将返回 -EINVAL 错误。
内核将查找 ctx 指向的内存块的元数据。元数据包含有关内存块大小和分配标志的信息。
内核将根据元数据中的分配标志将内存块归还给内核内存池。
内核将 ctx 设置为 NULL,以指示内存块已释放。

    
4.具体代码使用实践
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>MODULE_LICENSE("GPL");
MODULE_VERSION("0.2");static char gkptr;
struct myctx {u32 iarr[100];u64 uarr[100];char uname[128], passwd[16], config[16];
};
static struct myctx ctx;static int __init slab1_init(void)
{gkptr = kmalloc(1024, GFP_KERNEL);if (!gkptr) {WARN_ONCE(1, "kmalloc() failed!\n");goto out_fail1;}pr_info("kmalloc() succeeds, (actual KVA) ret value = %px\n", gkptr);print_hex_dump_bytes("gkptr before memset: ", DUMP_PREFIX_OFFSET, gkptr, 32);memset(gkptr, 'm', 1024);print_hex_dump_bytes(" gkptr after memset: ", DUMP_PREFIX_OFFSET, gkptr, 32);ctx = kzalloc(sizeof(struct myctx), GFP_KERNEL);if (!ctx)goto out_fail2;pr_info("context struct alloc'ed and initialized (actual KVA ret = %px)\n", ctx);print_hex_dump_bytes("ctx: ", DUMP_PREFIX_OFFSET, ctx, 32);return 0;        / success /out_fail2:kfree(gkptr);out_fail1:return -ENOMEM;
}static void __exit slab1_exit(void)
{kfree(ctx);kfree(gkptr);pr_info("freed slab memory, removed\n");
}module_init(slab1_init);
module_exit(slab1_exit);

5.注意事项

使用 slab、kmalloc、kzalloc 和 kfree 时的注意事项:

使用 slab 时,请考虑以下事项:

  1. 确保为要分配的内核对象类型创建了 slab 缓存。
  2. 仅使用 slab 缓存分配和释放内核对象。
  3. 避免为非内核对象分配 slab 缓存。
  4. 监视 slab 缓存的使用情况,以检测内存泄漏或碎片。

使用 kmalloc 和 kzalloc 时,请考虑以下事项:

  1. 仅在不需要使用 slab 缓存时使用 kmalloc 和 kzalloc。
  2. 始终使用 kzalloc 代替 kmalloc,除非您需要分配的内存不初始化为 0。
  3. 确保释放所有由 kmalloc 或 kzalloc 分配的内存。内存泄漏可能会导致系统不稳定。

使用 kfree 时,请考虑以下事项:

  1. 仅使用 kfree 释放由 kmalloc 或 kzalloc 分配的内存。释放非 slab 分配的内存可能会导致内核崩溃。
  2. 确保在释放之前无效化内存中的指针。这将有助于防止释放后使用悬空指针。
  3. 始终遵循内核文档中概述的最佳实践。
  4. 使用诸如 Valgrind 之类的工具来检测内存泄漏和使用错误。
  5. 定期审核代码以查找潜在的内存管理问题。
  6. 考虑使用 GFP_NOWAIT 标志来避免在内存分配失败时内核挂起。
  7. 考虑使用 GFP_DMA 标志来分配可用于 DMA 的内存。
  8. 考虑使用 vmalloc() 函数来分配大块连续内存。
6.最佳实践

使用 slab、kmalloc、kzalloc 和 kfree 的最佳实践以避免问题:

  1. 始终使用 kzalloc 代替 kmalloc,除非您需要分配的内存不初始化为 0。这将有助于防止使用未初始化的内存,从而导致未定义的行为。
  2. 释放所有由 kmalloc 或 kzalloc 分配的内存。内存泄漏可能会导致系统不稳定,甚至内核崩溃。
  3. 仅使用 kfree 释放由 kmalloc 或 kzalloc 分配的内存。释放非 slab 分配的内存可能会导致内核崩溃。
  4. 在释放之前无效化内存中的指针。这将有助于防止释放后使用悬空指针。
  5. 使用 slab 缓存来分配和释放内核对象。 slab 缓存旨在提高内核对象内存分配和释放的效率和可扩展性。
  6. 仅在不需要使用 slab 缓存时使用 kmalloc 和 kzalloc。这将有助于减少内存碎片。
  7. 监视 slab 缓存的使用情况,以检测内存泄漏或碎片。可以通过使用诸如 /proc/slabinfo 之类的工具来实现这一点。
  8. 使用诸如 Valgrind 之类的工具来检测内存泄漏和使用错误。这可以帮助您在问题导致系统不稳定之前识别并修复它们

避免问题的其他技巧:

  1. 考虑使用 GFP_NOWAIT 标志来避免在内存分配失败时内核挂起。这对于实时应用程序或对延迟敏感的代码非常有用。
  2. 考虑使用 GFP_DMA 标志来分配可用于 DMA 的内存。这对于需要直接内存访问的设备驱动程序非常有用。
  3. 考虑使用 vmalloc() 函数来分配大块连续内存。这对于分配超过单个页面大小的内存非常有用。
7.总结


通过学习上面教程,遵循这些最佳实践,您可以安全有效地使用 slab、kmalloc、kzalloc 和 kfree 来管理内核内存,并避免常见的内存管理问题。

这篇关于14 内核开发-slab 子系统,kmalloc、kzalloc 和 kfree的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/944412

相关文章

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并

基于Python开发PDF转PNG的可视化工具

《基于Python开发PDF转PNG的可视化工具》在数字文档处理领域,PDF到图像格式的转换是常见需求,本文介绍如何利用Python的PyMuPDF库和Tkinter框架开发一个带图形界面的PDF转P... 目录一、引言二、功能特性三、技术架构1. 技术栈组成2. 系统架构javascript设计3.效果图

基于Python开发PDF转Doc格式小程序

《基于Python开发PDF转Doc格式小程序》这篇文章主要为大家详细介绍了如何基于Python开发PDF转Doc格式小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用python实现PDF转Doc格式小程序以下是一个使用Python实现PDF转DOC格式的GUI程序,采用T

使用Python开发一个图像标注与OCR识别工具

《使用Python开发一个图像标注与OCR识别工具》:本文主要介绍一个使用Python开发的工具,允许用户在图像上进行矩形标注,使用OCR对标注区域进行文本识别,并将结果保存为Excel文件,感兴... 目录项目简介1. 图像加载与显示2. 矩形标注3. OCR识别4. 标注的保存与加载5. 裁剪与重置图像

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问