Bootstrap

Linux内存管理 页面置换算法

为了提高内存的利用率,解决内存供不应求的问题,更加合理的使用内存,引出了虚拟内存的概念。系统将内存暂时不需要的部分写入到硬盘,实现了对于扩展内存容量,所以叫虚拟内存,使得应用程序可以使用比实际物理内存更大的内存空间。前面我们了解了在进程运行过程中,当内存中存在空闲页的时候,系统如何实现这个虚拟内存管理的软硬件实现方式。如果内存中没有空闲页,那么就需要页面的调出,算法的好坏直接影响到系统的性能,本章的主要内容就是基于页面置换算法,其主要内容包括

置换算法的功能和目标
有哪些页面置换算法,各个算法的优缺点
linux采用什么样的内存置换算法
1. 页面置换算法
当出现缺页异常,需调入新页面而内存已满时,置换算法选择被置换的物理页面,其主要的目的是以尽可能减少页面的调入调出次数,把未来不再访问或短期内不访问的页面调出,以提高系统的性能。

1.1 局部页面置换算法
局部页面置换的选择范围仅限于当前进程占用的物理页面内,其主要由最优算法、先进先出算法、最近最久未使用算法,其基本的原理和特性如下图

在这里插入图片描述

1.2 全局页面置换算法
在局部算法里面并没有考虑各个进程之间的访存差异,全局置换算法为进程分配可变数目的物理页面。常驻集是指进程在运行时,当前时刻实际驻留在内存当中的页面集合。而工作集是进行再运行过程所固有的特征。置换算法的工作就是在进程的工作集的前提下,确定常驻集的大小以及相应页面。

对于全局置换算法,其又可以分为工作集置换算法和缺页率置换算法,其原理如下图

在这里插入图片描述

1.3 页面锁定
采用虚拟存储技术后,会产生缺页机制,缺页机制又会带来系统的开销,那么就会使得进程运行的时间变得越来越不确定,那么操作系统就导入了页面锁定技术,给每一个页增加一个页面锁定位。通过设置相应的锁定位,不让操作系统将操作系统使用的页面置换出内存,避免产生由交换过程带来的不确定性延迟,如以下的

1.操作系统核心代码
2.关键数据结构
3.I/O缓冲区
2. linux的页面置换算法
对于虚拟页式存储系统的工作的最佳状态,发生缺页的时候,系统中有大量的空闲页表,使得系统中保存一定数目的空闲页框。对于该问题,linux设计了一个分页的守护进程,多数的时候休眠,可定期唤醒以检查内存状态,其需要定时做以下操作

如果空闲页框过少,分页守护进程通过预定的页面置换算法选择页面换出内存
如果页面装入内存后被修改,则将他们写回磁盘,分页守护进程可保证所有的空闲页是干净的
对于本章的页面置换的算法,linux采用的是守护进程和缓冲技术来解决该问题,在后期的swap技术进项详细分析,本文只是大致了解了对于页面置换算法的一些基本的算法和特性,对于应该换出哪个页,何时进行页换入和换出,怎么进行页换入和换出机制,需要在swap章节进行详细分析。
 

3. 置换

3.3 置换和回

(1)两种

一种释放,一种PFRA(类似jvm 垃圾回收内存机

(2)页分类(按有无文件背景页面主要分两种

文件页(file-backed page):有文件背景页面。可以直接和硬盘对应的文件进行交

匿名页(anonymous page):无文件背景页面.如进程堆,栈,数据段使用的页等,无法直接跟磁盘交换,但是可以跟swap区进行交换

(3)哪些内存可以

a ) 属于内核的大部分页框是不能够进行回收的,比如内核栈、内核代码段、内核数据段以及大部分内核使用的页

b ) 进程使用的页框可以进行回收的,比如进程代码段,进程数据段,进程堆栈,进程访问文件时映射的文件页,进程间共享内存使用的页

c ) 伙伴系统分配的页面使用者使用free_pages之类的函数主动释放的,页面释放后被直接放归伙伴系统 slab中分配的对象(使用kmem_cache_alloc函数),也是由使用者主动释放的(使用kmem_cache_free函数)

(4) 页回收

a ) 页回写:如果一个很少使用的页的后备存储器是一个块设备(例如文件映射),则可以将内存直接同步到块设备,腾出的页面可以被重用 页交换:如果页面没有后备存储器,则可以交换到特定swap分区,再次被访问时再交换回内

b ) 页丢弃:如果页面的后备存储器是一个文件,但文件内容在内存不能被修改(例如可执行文件),那么在当前不需要的情况下可直接丢弃

页面该回收: 磁盘高速缓存的页面,但是如果页面是脏页面,则丢弃之前必须将其写回磁盘 回收匿名映射的页面,只好先把页面上的数据转储到磁盘,这就是页面交换(swap)。 所有的磁盘高速缓存页面都可回收,所有的匿名映射页面都可交换

(5) 页回收算法-L

磁盘高速缓存页面(包括文件映射页面)的链表、匿名映射页面的链表 当Linux系统内存有盈余时,内核会尽量多地使用内存作为page cache,提高系统性能,page cache会被加入到文件类型的LRU链表中,当系统内存紧张时,会按一定的算法来回收内

下面简单了解下: LRU链表按zone来配置,每个zone中都有一整套LRU链表.page交换调度策略使用.page可能被调度到active_list或者inactive_list队列里.就是使用lru这个list_head. LRU每个zone有两个链表,一个active,一个non-active

进行页面回收的时候,一是将active链表中最近最少使用的页面移动到inactive链表、二是尝试将inactive链表中最近最少使用的页面回收

(6) 页回收

直接页面回收(主动触发):“内存严重不足”事件的触发。 周期性回收(被动触发):kswapd进程以水线为触发点,按LRU链表来进行回收。系统会调用函数balance_pgdat(),它主要调用的函数是 shrink_zone() 和 shrink_slab(

(7) 反向映射(比如共享文件或者内

本质是逆向映

正向映射是建立进程页表和物理内存关系用于访问

逆向映射是回收的时候,查看反向指针rmap,没有页表引用就回收

多个引用的回收 PFRA处理页面回收的过程中,LRU的inactive链表中的某些页面可能就要被回收了

如果页面没有被映射,直接回收到伙伴系统即可(对于脏页,先写回、再回收)

否则,还有一件麻烦的事情要处理。因为用户进程的某个页表项正引用着这个页面呢,在回收页面之前,还必须给引用它的页表项一个交待 内核建立了从页面到页表项的反向映射。通过反向映射可以找到一个被映射的页面对应的vma,通过vma->vm_mm->pgd就能找到对应的页表。然后通过page->index得到页面的虚拟地址。再通过虚拟地址从页表中找到对应的页表项

(8) OOM( out of memory )kill

如果操作系统在进行了内存回收操作之后仍然无法回收到足够多的页面以满足上述内存要求,那么操作系统只有最后一个选择,那就是使用 OOM( out of memory )killer,它从系统中挑选一个最合适的进程杀死它,并释放该进程所占用的所有

3. 置换与回收

3.3 置换和回收

(1)两种情况

一种释放,一种PFRA(类似jvm 垃圾回收内存机制)

(2)页分类(按有无文件背景页面主要分两种):

文件页(file-backed page):有文件背景页面。可以直接和硬盘对应的文件进行交换。
匿名页(anonymous page):无文件背景页面.如进程堆,栈,数据段使用的页等,无法直接跟磁盘交换,但是可以跟swap区进行交换.

(3)哪些内存可以回收

a ) 属于内核的大部分页框是不能够进行回收的,比如内核栈、内核代码段、内核数据段以及大部分内核使用的页框。
b ) 进程使用的页框可以进行回收的,比如进程代码段,进程数据段,进程堆栈,进程访问文件时映射的文件页,进程间共享内存使用的页.
c ) 伙伴系统分配的页面使用者使用free_pages之类的函数主动释放的,页面释放后被直接放归伙伴系统 slab中分配的对象(使用kmem_cache_alloc函数),也是由使用者主动释放的(使用kmem_cache_free函数).

(4) 页回收方式

a ) 页回写:如果一个很少使用的页的后备存储器是一个块设备(例如文件映射),则可以将内存直接同步到块设备,腾出的页面可以被重用 页交换:如果页面没有后备存储器,则可以交换到特定swap分区,再次被访问时再交换回内存。
b ) 页丢弃:如果页面的后备存储器是一个文件,但文件内容在内存不能被修改(例如可执行文件),那么在当前不需要的情况下可直接丢弃。
页面该回收: 磁盘高速缓存的页面,但是如果页面是脏页面,则丢弃之前必须将其写回磁盘 回收匿名映射的页面,只好先把页面上的数据转储到磁盘,这就是页面交换(swap)。 所有的磁盘高速缓存页面都可回收,所有的匿名映射页面都可交换。

(5) 页回收算法-LRU

磁盘高速缓存页面(包括文件映射页面)的链表、匿名映射页面的链表 当Linux系统内存有盈余时,内核会尽量多地使用内存作为page cache,提高系统性能,page cache会被加入到文件类型的LRU链表中,当系统内存紧张时,会按一定的算法来回收内存.
下面简单了解下: LRU链表按zone来配置,每个zone中都有一整套LRU链表.page交换调度策略使用.page可能被调度到active_list或者inactive_list队列里.就是使用lru这个list_head. LRU每个zone有两个链表,一个active,一个non-active.
进行页面回收的时候,一是将active链表中最近最少使用的页面移动到inactive链表、二是尝试将inactive链表中最近最少使用的页面回收.

(6) 页回收时机

直接页面回收(主动触发):“内存严重不足”事件的触发。 周期性回收(被动触发):kswapd进程以水线为触发点,按LRU链表来进行回收。系统会调用函数balance_pgdat(),它主要调用的函数是 shrink_zone() 和 shrink_slab()。

(7) 反向映射(比如共享文件或者内存)

本质是逆向映射。
正向映射是建立进程页表和物理内存关系用于访问。
逆向映射是回收的时候,查看反向指针rmap,没有页表引用就回收.
多个引用的回收 PFRA处理页面回收的过程中,LRU的inactive链表中的某些页面可能就要被回收了。
如果页面没有被映射,直接回收到伙伴系统即可(对于脏页,先写回、再回收)。
否则,还有一件麻烦的事情要处理。因为用户进程的某个页表项正引用着这个页面呢,在回收页面之前,还必须给引用它的页表项一个交待 内核建立了从页面到页表项的反向映射。通过反向映射可以找到一个被映射的页面对应的vma,通过vma->vm_mm->pgd就能找到对应的页表。然后通过page->index得到页面的虚拟地址。再通过虚拟地址从页表中找到对应的页表项。

(8) OOM( out of memory )killer

如果操作系统在进行了内存回收操作之后仍然无法回收到足够多的页面以满足上述内存要求,那么操作系统只有最后一个选择,那就是使用 OOM( out of memory )killer,它从系统中挑选一个最合适的进程杀死它,并释放该进程所占用的所有页面

;