![](https://img-blog.csdnimg.cn/20201014180756918.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Linux内存管理
文章平均质量分 91
讲解一些Linux内存管理的东西
追捕的风
这个作者很懒,什么都没留下…
展开
-
(十六)Linux内存管理之CMA
1. 概述Contiguous Memory Allocator, CMA,连续内存分配器,用于分配连续的大块内存。CMA分配器,会Reserve一片物理内存区域:设备驱动不用时,内存管理系统将该区域用于分配和管理可移动类型页面; 设备驱动使用时,用于连续内存分配,此时已经分配的页面需要进行迁移;此外,CMA分配器还可以与DMA子系统集成在一起,使用DMA的设备驱动程序无需使用单独的CMA API。2. 数据结构内核定义了struct cma结构,用于管理一个CMA区域,此外还定义了全局转载 2022-01-13 16:13:37 · 2503 阅读 · 2 评论 -
(十五)Linux内存管理之RMAP
1. 概述RMAP反向映射是一种物理地址反向映射虚拟地址的方法。 映射 页表用于虚拟地址到物理地址映射,其中的PTE页表项记录了映射关系,同时struct page结构体中的mapcount字段保存了有多少PTE页表项映射了该物理页。 反向映射 当某个物理地址要进行回收或迁移时,此时需要去找到有多少虚拟地址射在该物理地址,并断开映射处理。在没有反向映射的机制时,需要去遍历进程的页表,这个效率显然是很低下的。反向映射可以找到虚拟地址空间VMA,并仅从VMA使用的用户页表中取消映射,可以转载 2022-01-13 16:13:30 · 373 阅读 · 0 评论 -
(十四)Linux内存管理之page fault处理
1. 概述上篇文章分析到malloc/mmap函数中,内核实现只是在进程的地址空间建立好了vma区域,并没有实际的虚拟地址到物理地址的映射操作。这部分就是在Page Fault异常错误处理中实现的。Linux内核中的Page Fault异常处理很复杂,涉及的细节也很多,malloc/mmap的物理内存映射只是它的一个子集功能,下图大概涵盖了出现Page Fault的情况:下边就开始来啃啃硬骨头吧。2. Arm64处理Page Fault的异常处理,依赖于体系结构,因此有必要来介绍一下转载 2022-01-13 16:13:20 · 1148 阅读 · 0 评论 -
(十三)Linux内存管理之vma/malloc/mmap
1. 概述这篇文章,让我们来看看用户态进程的地址空间情况,主要会包括以下:vma; malloc; mmap;进程地址空间中,我们常见的代码段,数据段,bss段等,实际上都是一段地址空间区域。Linux将地址空间中的区域称为Virtual Memory Area, 简称VMA,使用struct vm_area_struct来描述。在进行内存申请和映射时,都会去地址空间中申请一段虚拟地址区域,而这部分操作也与vma关系密切,因此本文将vma/malloc/mmap三个放到一块来进行分析。开转载 2022-01-13 16:13:12 · 693 阅读 · 0 评论 -
(十二)Linux内存管理之vmap与vmalloc
1. 概述在之前的系列文章中,分析到了Buddy System的页框分配,Slub分配器的小块内存对象分配,这些分配的地址都是物理内存连续的。当内存碎片后,连续物理内存的分配就会变得困难,可以使用vmap机制,将不连续的物理内存页框映射到连续的虚拟地址空间中。vmalloc的分配就是基于这个机制来实现的。还记得下边这张图吗?vmap/vmalloc的区域就是在VMALLOC_START ~ VMALLOC_END之间。开启探索之旅吧。2. 数据结构2.1 vmap_area/vm转载 2022-01-13 16:13:06 · 932 阅读 · 0 评论 -
(十一)Linux内存管理slub分配器
1. 概述之前的文章分析的都是基于页面的内存分配,而小块内存的分配和管理是通过块分配器来实现的。目前内核中,有三种方式来实现小块内存分配:slab, slub, slob,最先有slab分配器,slub/slob分配器是改进版,slob分配器适用于小内存嵌入式设备,而slub分配器目前已逐渐成为主流块分配器。接下来的文章,就是以slub分配器为目标,进一步深入。先来一个初印象:2. 数据结构有四个关键的数据结构:struct kmem_cache:用于管理SLAB缓存,包括该缓存中对转载 2022-01-13 16:12:52 · 457 阅读 · 0 评论 -
(十)Linux内存管理 - zoned page frame allocator - 5
1. 概述本文将讨论memory reclaim内存回收这个话题。在内存分配出现不足时,可以通过唤醒kswapd内核线程来异步回收,或者通过direct reclaim直接回收来处理。在针对不同的物理页会采取相应的回收策略,而页回收算法采用LRU(Least Recently Used)来选择物理页。直奔主题吧。2.LRU和pagevec2.1 数据结构简单来说,每个Node节点会维护一个lrvvec结构,该结构用于存放5种不同类型的LRU链表,在内存进行回收时,在LRU链表中检索.转载 2022-01-11 21:40:21 · 314 阅读 · 0 评论 -
(九)Linux内存管理 - zoned page frame allocator - 4
1. 概述本文将描述memory compaction,内存碎片整理技术。内存碎片分为内碎片和外碎片:内碎片:内存页里边的碎片; 外碎片:内存页之间的碎片,可能会造成连续物理页面分配失败。memory compaction就是通过将正在使用的可移动页面迁移到另一个地方以获得连续的空闲页面的方法。针对内存碎片,内核中定义了migrate_type用于描述迁移类型:MIGRATE_UNMOVABLE:不可移动,对应于内核分配的页面; MIGRATE_MOVABLE:可移动,对应于从用户空..转载 2022-01-11 21:38:48 · 253 阅读 · 0 评论 -
(八)Linux内存管理 - zoned page frame allocator - 3
1. 概述本文将分析watermark。简单来说,在使用zoned page frame allocator分配页面时,会将可用的free pages与zone的watermark进行比较,以便确定是否分配内存。同时watermark也用来决定kswapd内核线程的睡眠与唤醒,以便对内存进行检索和压缩处理。回忆一下之前提到过的struct zone结构体:struct zone { /* Read-mostly fields */ /* zone watermarks, access转载 2022-01-11 21:37:26 · 251 阅读 · 0 评论 -
(七)Linux内存管理 - zoned page frame allocator - 2
1. 概述本文将分析Buddy System。Buddy System伙伴系统,是通过将物理内存划分为页面来进行管理的系统,支持连续的物理页面分配和释放。此外,使用与碎片相关的算法来确保最大的连续页面。先通过一个例子大体介绍一下原理吧:空闲的物理页框按大小分组成0~MAX_ORDER个链表,每个链表存放页框的大小为2的n次幂,其中n在0 ~ MAX_ORDER-1中取值。假设请求分配2^8 = 256个页框块:检查n = 8的链表,检查是否有空闲块,找到了则直接返回; 没有找到满足需求的转载 2022-01-11 21:36:14 · 186 阅读 · 0 评论 -
(六)Linux内存管理 - zoned page frame allocator - 1
1. 介绍之前的系列内存管理文章基本上描述的是物理页面的初始化过程,以及虚拟页面到物理页面的映射建立过程,从这篇文章开始,真正要涉及到页面的分配了。接下来的文章会围绕着分区页框分配器(zoned page frame allocator)来展开,其中会包含大家熟知的Buddy System分析。本文会先围绕着涉及到的数据结构,以及大体的流程做一个整体的分析,后续会针对这个流程中的细节进行更详细的拆解,我已经迫不及待了。2. 数据结构2.1 概述先回顾一下(五)Linux内存管理zone_转载 2022-01-11 21:35:00 · 221 阅读 · 0 评论 -
(五)Linux内存管理zone_sizes_init
1. 介绍在(四)Linux内存模型之Sparse Memory Model中,我们分析了bootmem_init函数的上半部分,这次让我们来到下半部分吧,下半部分主要是围绕zone_sizes_init函数展开。前景回顾:bootmem_init()函数代码如下:void __init bootmem_init(void){ unsigned long min, max; min = PFN_UP(memblock_start_of_DRAM()); max = PFN_DOWN(m转载 2022-01-11 18:49:55 · 546 阅读 · 0 评论 -
(四)Linux内存模型之Sparse Memory Model
1. 介绍顺着之前的分析,我们来到了bootmem_init()函数了,本以为一篇文章能搞定,大概扫了一遍代码之后,我默默的把它拆成了两部分。bootmem_init()函数代码如下:void __init bootmem_init(void){ unsigned long min, max; min = PFN_UP(memblock_start_of_DRAM()); max = PFN_DOWN(memblock_end_of_DRAM()); early_memtest(mi转载 2022-01-11 18:47:51 · 473 阅读 · 1 评论 -
(三)Linux paging_init解析
1. 介绍从(二)Linux物理内存初始化中,可知在paging_init调用之前,存放Kernel Image和DTB的两段物理内存区域可以访问了(相应的页表已经建立好)。尽管物理内存已经通过memblock_add添加进系统,但是这部分的物理内存到虚拟内存的映射还没有建立,可以通过memblock_alloc分配一段物理内存,但是还不能访问,一切还需要等待paging_init的执行。最终页表建立好后,可以通过虚拟地址去访问最终的物理地址了。按照惯例,先上图,来一张ARM64内核的内存布局图片吧转载 2022-01-11 18:46:03 · 445 阅读 · 0 评论 -
(二)Linux物理内存初始化
1. 介绍让我们思考几个朴素的问题?系统是怎么知道物理内存的? 在内存管理真正初始化之前,内核的代码执行需要分配内存该怎么处理?我们先来尝试回答第一个问题,看过dts文件的同学应该见过memory的节点,以arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi为例: memory@80000000 { device_type = "memory"; reg = <0x00000000 0x80000000 0 0x80000000>转载 2022-01-11 18:36:05 · 817 阅读 · 0 评论 -
(一)ARMv8 MMU及Linux页表映射
1. 介绍要想理解好Linux的页表映射,MMU的机制是需要去熟悉的,因此将这两个模块放到一起介绍。关于ARMv8 MMU的相关内容,主要参考文档:《ARM Cortex-A Series Programmer’s Guide for ARMv8-A》。2. ARMv8 MMU2.1 MMU/TLB/Cache概述MMU:完成的工作就是虚拟地址到物理地址的转换,可以让系统中的多个程序跑在自己独立的虚拟地址空间中,相互不会影响。程序可以对底层的物理内存一无所知,物理地址可以是不连续的,但是不转载 2022-01-11 18:33:44 · 1809 阅读 · 2 评论