7月前
[linux内存管理] 第025篇 细节拉满,80 张图带你一步一步推演 slab 内存池的设计与实现
本文介绍了 Linux 内核中的 slab 内存池,用于高效地分配和释放小内存块。作者首先回顾了 Linux 内存分配的宏观流程,然后引出 slab 内存池的产生背景和优势。slab 内存池将频繁使用的小内存块池化,避免了频繁的内存分配和释放带来的性能开销。文章详细介绍了 slab 对象池的内存布局,包括对齐、red zone、freepointer 和状态信息等。接着,文章分析了 slab 的总体架构设计,包括 kmem_cache、kmem_cache_cpu 和 kmem_cache_node 等数据结构。最后,文章详细介绍了 slab 内存分配和释放的原理,包括从本地 cpu 缓存、partial 列表、NUMA 节点缓存和伙伴系统中分配和释放内存的场景。
7月前
[linux内存管理] 第024篇 slab内存分配器概述
Buddy系统以页为单位分配内存,导致浪费和效率低下。Solaris的Slab分配器通过对象类型专属仓库和缓存复用,极大提升命中率和访问速度。Linux随后演化出SLUB和SLOB,其中SLUB采用批量、无锁和本地CPU缓存等机制,大幅降低元数据开销与碎片化,优化了性能。
10月前
[linux内存管理] 第023篇 watermark详解
本文探讨了 Linux 内存管理中的水位机制,特别是 `zoned page frame allocator` 如何使用水位来控制内存分配和回收。文章首先介绍了 `struct zone` 结构体和三种水位 `WMARK_MIN`、`WMARK_LOW` 和 `WMARK_HIGH` 的概念及其作用。随后,文章详细分析了水位的初始化过程,包括计算 `min_free_kbytes`、更新内存区水位、刷新内存区统计阈值和初始化低内存保留等步骤。接着,文章讨论了快速分配和慢速分配中的水位检测机制,以及 `kswapd` 和内存规整过程中的水位检测。最后,文章强调了调整内存水位的重要性,以及如何根据不同业务场景进行优化。
11月前
[linux内存管理] 第022篇 buddy内存管理之慢速分配
**本文分析了 Linux 内核中慢速内存分配路径 `__alloc_pages_slowpath`,该路径在快速分配失败时被触发。慢速分配尝试通过多种手段获取内存,包括内存回收、内存压缩和唤醒 kswapd 线程等**。 **主要步骤如下**: 1. **判断是否允许直接回收内存**:根据 GFP 标志判断是否可以进行直接内存回收。 2. **判断是否为高成本请求**:根据请求的 order 和 migratetype 判断是否为高成本请求。 3. **尝试直接内存压缩**:在高成本请求或无法访问预留内存的情况下,尝试进行直接内存压缩。 4. **唤醒 kswapd 线程**:唤醒 kswapd 线程进行内存回收。 5. **尝试再次分配内存**:根据新的分配标志和 zonelist 尝试再次分配内存。 6. **直接内存回收**:如果允许直接回收内存,则尝试进行直接内存回收。 7. **再次尝试分配内存**:在内存回收后再次尝试分配内存。 8. **尝试内存压缩**:如果直接内存回收失败,则尝试进行内存压缩。 9. **处理 CPU 集合更新**:检查 CPU 集合是否更新,并进行相应的处理。 10. **启动 OOM 杀手**:如果所有尝试都失败,则启动 OOM 杀手进程。 11. **重试分配**:如果 OOM 杀手进程有所进展,则重试分配。 **慢速分配路径的关键在于通过各种手段增加空闲内存,以便能够成功分配请求的内存**。 **总结来说,慢速分配路径是 Linux 内核中保证内存分配可靠性的重要机制,它通过多种手段应对内存不足的情况,确保系统能够正常运行**。
11月前
[linux内存管理] 第021篇 buddy内存管理之快速分配
深入解析Linux buddy分配器的alloc_pages核心算法,详述内存分配的“快速分配”与“慢速分配”流程。通过源码剖析,呈现alloc_pages如何高效处理内存请求,包括gfp标志、NUMA节点选择、碎片优化及分配策略,突出快速分配优先从zone链表获取空闲页,未命中时转入慢速路径处理回
11月前
[linux内存管理] 第020篇 Linux内核slab内存的越界检查SLUB_DEBUG的原理剖析
越界访问常引发难以定位的系统异常,尤其在驱动开发中隐蔽性极高。SLUB DEBUG通过在分配内存对象周围设置特殊区域和magic数,有效检测越界(OOB)、用后即弃(UAF)等问题。借助Red zone和padding机制,能精准发现内存溢出及链表破坏,搭配slabinfo工具主动触发检测。
2025-01-07
[linux内存管理] 第019篇 buddy分配器基础知识以及分配器api接口
本文主要介绍了Linux内存管理中的伙伴系统,它是Linux内核中基本的内存分配系统,涉及页面分配、页面回收、页面规整等机制。文章详细剖析了快速分配之前的一些基础知识,包括分配掩码、分配标志、分配的API接口以及Linux对于伙伴系统的设计思路。伙伴系统将空闲页面分成11个块链表,每个块链表管理着2的幂次方个连续页面,内存管理框图展示了其组织结构。同时,文章还解释了内存块是如何连接的,以及伙伴系统的合并机制。
2025-01-06
[linux内存管理] 第018篇 buddy系统的简介以及初始化
本文深入剖析了Linux内存管理中伙伴系统的初始化流程。伙伴系统是Linux内核用于管理和分配物理内存页面的核心算法,它将内存分成大小为2的幂次方的内存块,并通过“伙伴”机制进行分配和回收。文章详细介绍了伙伴系统的数据结构,包括`struct free_area`和`struct zone`,以及迁移类型`migratetype`和区域请求标志`__GFP区域请求标志`。此外,文章还分析了fallbacks机制和`pageblock_order`的定义。最后,文章通过分析`mm_init`函数和`memblock_free_all`函数,揭示了伙伴系统初始化的详细过程,包括释放未使用的内存、重置zone的`managed_pages`、将内存块添加到伙伴系统等操作。通过本文的解析,读者可以更好地理解Linux内存管理中伙伴系统的工作原理和初始化过程。
2025-01-06
[linux内存管理] 第017篇 zonelist的初始化
本文主要分析了Linux内核中zonelist的初始化过程。首先介绍了两个关键数据结构:`pglist_data`和`zonelist`,其中`pglist_data`包含了一个`node_zonelists`数组,用于管理内存节点的zone信息;`zonelist`结构体则包含了一个`zoneref`数组,用于描述一个node的各个zone的信息。接着详细阐述了zonelist的初始化过程,包括`build_all_zonelists`、`build_zonelists`和`build_zonerefs_node`三个关键函数。最后,总结了zonelist的初始化过程,并附上了初始化过程的示意图。
2025-01-06
[linux内存管理] 第016篇 /proc/iomem的详细解析
本文详细介绍了Linux内核中`/proc/iomem`节点的构建与显示过程。文章首先指出`/proc/iomem`展示的是物理内存的使用情况,并通过`request_standard_resources`函数将内存区域挂载到资源树。文章进一步解析了`/proc/iomem`的注册过程,包括`ioresources_init`函数和`iomem_resource`资源树,以及数据来源和显示逻辑。最后总结,`/proc/iomem`通过遍历资源树和格式化输出,提供了系统物理内存布局的详细视图,对资源管理和调试具有重要作用。