os-9.虚拟内存

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了os-9.虚拟内存相关的知识,希望对你有一定的参考价值。

9.虚拟内存

背景

虚拟内存——将用户逻辑内存与物理内存分开

  • 只需要执行的部分程序调入内存
  • 逻辑地址可以比物理地址空间大的多
  • 允许多个进程之间共享地址空间
  • 允许更有效的进程创建

按需调页

demand paging,在需要时才调入相应的页(即lazy swapper懒惰交换)

按需调页=分页+缺页+页置换

优点:更少IO,更少内存,更快反应,更多用户

基本概念

有效-无效位 valid-invalid bit,页表存储哪些页在内存中

技术分享图片

对标记为i的页访问会产生缺页错误 page fault

处理缺页错误的程序如下:

  1. 检查页表确认该引用是否合法
  2. 引用非法则终止进程,引用有效则调入
  3. 找到一个空闲帧
  4. 交换页
  5. 重置页表
  6. 重新开始因缺页错误而中断的指令

技术分享图片

按需调页的性能

设p为缺页错误的概率,则有效访问时间(EAT)=(1-p)*ma+p*页错误时间

ma为内存访问时间一般为200ns

页错误时间包括:1处理页错误中断,2页换入换出,3重启进程,一般为8ms

若页错误为1/1000,则EAT=8.2us,慢了近40倍

实现按需调页,需要考虑两个问题:帧分配,页置换

写时复制

copy-on-write,COW允许父进程和子进程共享页,只有在修改某一页时才对该页进行拷贝(需要写保护)

空闲页通常通过空闲缓冲池由按需填零技术分配页,ZFOD(zero-fill-on-demand)

页面置换

page replacement

当内存过度分配使无空闲页时,操作系统有如下选择

  1. 终止用户进程
  2. 交换出一个进程
  3. 页置换

基本页置换

页错误处理程序:

  1. 查找所需页在磁盘的位置

  2. 查找一个空闲帧

a. 若有空闲帧,直接使用

b. 若无空闲帧,使用页置换算法找到一个牺牲帧 victim frame

c. 将牺牲帧写入磁盘,改变页表和帧表

  1. 将所需页读入到空闲帧,改变页表和帧表

  2. 重启用户进程

页置换过程如下:

技术分享图片

可以通过修改位或脏位来降低开销(modify bit,dirty bit)。若修改位没有设置,当该页被选为替换页时,则无需写入磁盘,降低了一半的I/O

FIFO页置换

使用队列管理,队首的页被置换

Belady异常,当帧数增加时,页错误率不一定总是下降

最优置换

Optimal page-replacement,OPT错误率最低,没有Belady异常

从未来看,替换最长时间不会使用的页

技术分享图片

缺点:难以实现

LRU页置换

least-recently-used algorithm,最近最少使用算法

从历史看,替换最长时间不会使用的页

技术分享图片

实现

  • 计数器:每一项关联时间项,每次内存引用,将计时器的值赋给新的页,选择最小的页置换

技术分享图片

  • 栈实现:每次替换栈底

技术分享图片

注意上述两种方式对无页替换时仍需设置相应的值,如下面栈的模拟

技术分享图片

近似LRU算法

通常没有足够的硬件支持LRU算法,更简单的情况,对每一页设置一个引用位 reference bit,来表示是否被使用

  1. 附加引用位算法

为每一页保留一个8位字节,在规定的时间段后,os把每个页的引用位转移到8位字节的最高位,右移其他位。则8位寄存器保存了过去8个周期内的使用情况,每次置换值最小的页(更大的值意味着更近被使用)

  1. 二次机会算法

若引用位为0,则替换

若引用位为1,则改为0,放进内存队列,选择下一页

  1. 增强型二次机会算法

将引用位和修改位共同考虑,按照(0,0)-(0,1)-(1,0)-(1,1)的顺序来置换

基于计数的页置换

  • 最不经常使用页置换算法LFU:置换最小计数的页
  • 最常使用页置换算法MFU:最小次数的页刚调进来且还没有使用

帧分配算法

给每个进程分配多少帧内存的问题

帧的最少数量

越少页错误越多,至少有足够的帧完成单个指令

最少数量由体系结构决定,最大由物理内存决定

分配算法

  • 平均分配
  • 比例分配 proportional allocation

根据进程的大小划分比例

根据优先级划分比例

全局分配与局部分配

全局置换:从所有帧集合中选择一个置换帧

局部置换:每个进程仅从自己的分配帧中进行选择

全局置换可能从低优先级的进程抢帧,增加自己的帧数量。不能控制页错误率。但通常系统吞吐量更好,更常用

系统颠簸

Thrashing(进程没有足够的帧,产生页错误,选择一个正在使用的页置换,但很快又再次需要这一页。这样反复产生页错误,置换页)频繁的页调度行为,在换页上花费的时间多于执行的时间

原因

操作系统发现cpu使用率低,引入新进程

新进程需要更多帧,出现页错误,从其他进程拿到帧,这些进程再从另外进程拿帧

就绪队列变空,进程等待调页设备

cpu使用率降低,引入更多的进程,更多的页错误,更长的队列等待调页设备

出现系统颠簸,吞吐量下降,页出错显著增加

解决:分配满足进程当前局部的帧

工作集合模型

\(\Delta\)为工作集合窗口,检查在过去\(\Delta\)个页的引用的集合定义为工作集合,如图\(\Delta\)为10时

技术分享图片

每个进程的工作集合大小为\(WSS_i\),则总的帧需求量D
\[ D=\sum WSS_i \]
当D大于可用帧的数量则可能出现颠簸,即系统控制总帧数少于可用帧的总数即可

系统追踪每个进程的工作集合,并为其分配大于工作集合的帧数,若还有空闲帧则启动另一个进程。若所有工作集合之和的增加超过了可用帧的总数,则选择暂停一个进程,该进程的页被写出,且其帧分配给其他进程。挂起的进程可稍后重启

跟踪工作集合:

\(\Delta\)取10000,

  1. 5000个引用产生定时中断
  2. 每一页设置两位
  3. 中断时复制所有引用,清除所有引用位
  4. 若有一位为1,则认为处于工作集合中

页错误频率

page-fault frequency,PFF,解决颠簸的另一种方法

若实际错误率超过上限,则分配更多的帧;若低于下限,则从该进程中移走帧(利用率不足)

内存映射文件

memory mapping,运用虚拟内存技术,将文件I/O作为内存访问

基本机制

通过内存操作文件而不是系统调用read()和write(),简化了文件访问和使用

多个进程间文件的共享

技术分享图片

windows的实现方式

技术分享图片

内核内存的分配

一般通过空闲内存池分配

  1. 内核有些数据结构不需要一页内存
  2. 有的需要连续内存

Buddy系统

按照2的幂来分配

技术分享图片

优点:可通过合并快速形成更大的段

缺点:容易产生碎片(33KB只能用64KB来满足)

slab分配

slab由一个或多个物理上连续的页组成,cache含有一个或多个slab,每个内核数据结构有一个cache

技术分享图片

优点:无碎片(slab与对象大小相等),内存请求可快速满足(slab预创建)

其他考虑

预调页

prepaging,问题在于采用预调页的成本是否小于处理相应页错误的成本

页大小

  • 碎片——更小页
  • 页表大小——更大页
  • I/O花费——更大页
  • 局部性——更小页
  • 页错误——更大页

总的来说趋向更大页

TLB范围

TLB条数与页大小之积

通常,工作集合位于TLB中

一味增加页大小会造成碎片化,可提供多种页大小

程序结构

Program 1   
        for (j = 0; j <128; j++)        
            for (i = 0; i < 128; i++)                  
                data[i,j] = 0;
128 x 128 = 16,384 page faults 
Program 2   
        for (i = 0; i < 128; i++)         
            for (j = 0; j < 128; j++)
                data[i,j] = 0;
128 page faults

I/O互锁

用于I/O的页必须不被替换算法替换,即允许页锁在内存中——lock bit

操作系统实例

Windows XP

通过簇来实现虚拟内存 clustering

  • 进程创建时设置工作集合最小值和最大值
  • 若进程的页数低于工作集合最小值且发生页错误,则分给更多帧;若进程的页数达到工作集合最大值且发生页错误,则采取局部置换
  • 当空闲内存的量低于阈值时,采用自动工作集合修整

若进程分配的帧数大于工作集合最小值,则删除帧知道进程等于最小值,一旦有足够的空闲内存,再分配给帧数为工作集合最小值的进程

Solaris

os需要维护足够多的空闲内存

技术分享图片

  1. 空闲页数低于lostsfree(1/64),启动换页进程,每秒检查4次

双指针轮转算法:时钟的第一个指针扫描内存所有页,将其引用位置0,之后时钟的第二个指针将引用位仍为0的页加到空闲链表

  1. 空闲页低于desfree,每秒启动100次换页进程,30秒内不能增加超过desfree,则开始交换进程(失去该进程所有页)
  2. 空闲页低于minfree,每次请求新页时换页


以上是关于os-9.虚拟内存的主要内容,如果未能解决你的问题,请参考以下文章

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

详解Jvm内存结构

详解Jvm内存结构

详解Jvm内存结构

java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段

Android中的内存泄漏和内存溢出