linux内存管理

内存分配机制

linux中将内存区域分为了3块

  • DMA
  • NORMAL:OS占用的内存空间
  • HIGH:非OS占用的内存空间

虚拟内存

作用如下:

  • 提供了进程间的数据共享
  • 实现了物理内存按需分页
  • 降低了使用物理内存的门槛

虚拟内存的管理使用了红黑树,key为起始地址,value为vma

MMU

memory management unit,也叫分页内存管理单元。它负责虚拟地址到物理地址的转换(虚拟内存管理),内存保护和中央处理器高速缓存的控制。

NUMA

Non-uniform memory access,非均匀访存模型。它是一种为多处理器的电脑设计的内存架构,内存访问时间取决于内存相对于处理器的位置。在NUMA下,处理器访问它自己的本地内存的速度比非本地内存(内存处于另一个处理器,或者是处理器之间共享的内存)要快一些。

zone

在NUMA中,每一个处理器的本地内存被认为是一个节点(node),而每一个node又被划分为多个内存管理区域,这些区域就是zone。zone也有3种

  • zone_dma
  • zone_normal
  • zone_high

三级缓存机制

  1. 一级缓存可以分为一级数据缓存(Data Cache,D-Cache)和一级指令缓存(InstructionCache,I-Cache)。
  2. 每一个CPU内部都会有一个二级缓存
  3. 三级缓存由所有CPU共享

现在的缓存一般都采用SRAM存储器实现

大内存的分配

大内存的分配一般是使用伙伴算法,以页为基本单位,每次分配1个或多个页,伙伴算法可以看下图
在这里插入图片描述

linux将所有的空闲页框分组为11块链表,每一块链表分别包含大小为1,2,4,8,16,32,64,128,256,512和1024的连续页框,其中每一个页框的大小是4KB。
举个例子来说明伙伴算法。比如现在需要分配4个页框大小的空间,就直接从2号块拿出一个4块连续的页框空间进行分配

slab

伙伴算法只能针对大空间进行分配,它可以避免外部碎片的产生,但无法避免内部碎片的产生。slab算法针对小对象的分配,可以避免产生内部碎片。
slab算法的整体结构如图所示(图片截自https://www.bilibili.com/video/BV1wk4y1y7gL?from=search&seid=10125783671322033796)
在这里插入图片描述
每一块高速缓存都由多个slab组成,每一个slab中存储了多个对象(每个对象的大小都是相同的)。详细的可以看下面这张图(图片截自https://www.bilibili.com/video/BV1wk4y1y7gL?from=search&seid=10125783671322033796)
在这里插入图片描述

slab分为slab_full(存满的slab),slab_partial(只用了一部分的slab),slab_free(完全没用的slab)

例如要分配128B大小的对象,选择object_size=128B的高速缓存,然后再从中选择slab_partial或者slab_free进行对象的分配

内存回收机制

内存的回收使用LRU(最近最少使用)算法。linux在具体实现时设置了active_list和inactive_list两个队列。

  • active_list存储最近使用的页
  • inactive_list存储最近未使用的页
    两个队列都是队头添加元素,队尾删除元素。

页标记

active_list队列中的页PG_active都会被标记为1,而inactive_list队列中的页的PG_active会被标记为0。

具体流程

  • 当inactive_list中的页被访问时,如果它的PG_referenced=1则将该页从inactive_list中移除,然后添加到active_list中,如果PG_referenced=0,则只将PG_referenced置为1

  • 需要进行页的淘汰时,会淘汰inactive_list队尾PG_referenced=0的页。因为PG_referenced=1的页表示该页在inactive_list中被访问了一次。

  • 同样,如果active_list队列满了,要从队尾淘汰PG_referenced=0的页,将其放入inactive_list中。但如果active_list队尾的页PG_referenced=1,则将该页重新加入到active_list队头,同时PG_referenced设为0

存在的问题

定义当页面刚被回收,又马上被访问到,这样产生的缺页中断叫refault。

  1. 当inactive_list比较长时可以保证每个页面在被回收前有充分的时间再次被访问到,这样可以减少refault的数量,但是内存是有限的,inactive_list太长了,actifve_list就比较短了。那么要怎么平衡二者的长度?

我们可以在页面被回收时记录一个timestamp1,当该页面refault被换入时再记录一个timestamp2。接着我们可以比较该页面再次被换出时经历的时间与timestamp2和timestamp1的差值的大小,如果前者较大说明页面可以在inactive_list中再次被访问到,此时的inactive_list长度适中,否则就要增加inactive_list的长度了。实现时我们使用计数值来代替timestamp。

  1. 多个cpu访问对active_list和inactive_list执行add和delete操作,这两个队列是需要进行加锁操作的,但频繁的加锁对于性能的影响是比较大的。所以每次的add和delete操作都是先将被操作的节点加入到lur cache中,当lru cache的大小达到某个阈值(15个页面)时,再获取锁将这15个页面一起加入或者从队列中删除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值