谈谈对内存管理子系统的理解

内存管理子系统主要做两件事:

  1. 管理虚拟地址和物理地址的映射;2. 管理物理内存的分配

内存管理,可以分为两个阶段,启动阶段和启动完成后。
在启动阶段,使用的是启动内存分配器,这个分配器功能有限,只能做一些简单的分配、回收任务。
启动完成后,内存子系统的各个模块就启动起来了,包括伙伴系统、slab分配器、kswapd、kcompactd等等子模块都起来了,这些模块组成了整个内存管理子系统。

上面是从阶段来看内存管理,从被管理的内存角度来看,内存管理还能够被分为虚拟内存管理以及物理内存管理。
在有MMU的soc里,我们的代码一般操作的是虚拟内存,通过页表以及MMU最终映射到了物理内存。对于虚拟内存,每个进程有他自己独立的进程地址空间,进程通过主要mm_struct结构体以及vma结构体管理这个进程的虚拟内存,进程之间的内存地址空间通过页表以及MMU的作用能够做到相互隔离,互不影响;进程的虚拟内存空间分为了用户态内存地址空间以及内核内存地址空间,用户态内存地址空间又分成了代码段、数据段、堆、栈、mmap等等区域,内核内存地址空间分为了线性地址区、vmalloc区等等;
物理内存的话,管理的数据结构,主要是使用了三层数据结构,最顶层是内存节点pglist_data,每个内存节点下根据内存区域的性质分成一个个zone,又把每个zone划分为一个个页框page;分配和回收方面,主要通过伙伴算法、slab分配器进行分配,辅以内存回收、内存规整来应对一些伙伴算法和slab分配器存在的缺陷。

内存的分配的回收,是内存管理最主要的内容。关于进程的虚拟内存地址空间的分配和回收,我理解没有用到什么特别的算法,主要是通过mm_struct里一个双链表以及一颗红黑树管理这个进程的虚拟内存。分配虚拟内存的主要函数有mmap以及brk。
物理内存的分配和回收,内核使用了几个兼顾性能以及效果的分配算法。伙伴算法的最小分配单位是页,他是一种兼顾分配效率以及外部碎片的内存分配算法,主要用于较大的内存分配的场景;slab分配器,是为了不同大小的对象而设计的一个分配算法,并兼顾效率以及碎片化程度;slab分配器是基于伙伴算法的,slab分配器从伙伴分配器那边拿到内存后,将内存切成一小块一小块,类似内存池那种感觉,主要应用在小内存分配的场景,比如内核的kmalloc就是基于slab分配器实现的。

另外,内存管理还有一个非常重要的函数:缺页中断处理函数。linux内核的内存分配使用的惰性分配的原则,一般情况下(像mmap传入了MAP_LOCK或MAP_POPULATE参数才会把物理内存也分配了),我们给进程分配虚拟地址空间后,并不会马上就分配物理内存,物理内存会在进程第一次访问对应虚拟内存时触发一个缺页中断后分配。缺页中断会根据该虚拟地址空间是匿名页/文件页、是否被写入了swap分区中、是否是写时复制等情况进行处理,最后的结果就是分配一块物理内存,完成内存映射,并载入相应的内容。

此外,内存的一些迁移、KSM、kswapd、khugepaged线程,在后台处理用户态进程的内存,除了给用户带来内存非常多的假象之外,还需要注意与用户态对内存读写的并发问题,不能为了节省内存而引发用户态的功能错误。

在这里插入图片描述
再借用网上的一个画的非常好的图,来从整个系统角度来看内存是怎么按照粒度被管理的(这里没有考虑node和zone的概念):
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值