操作系统交换空间机制和策略


交换空间机制

交换空间:在硬盘上的一部分空间,用于物理页的移入和移除。页的相关概念见《虚拟内存发展史》。将内存中的页交换到硬盘上,需要的时候再交换回去。

在windows中,交换空间被叫做虚拟内存(不同于进程的虚拟内存):

image-20210823151947462

linux下可以直接top或htop查看:

image-20210823150513659

虚拟内存并不是必须的,但是有会好一些,不然内存不够了就意味着有的进程会被操作系统kill掉。所以我的服务器在vscode远程写代码的时候有时候vscode会被kill。

image-20210823151035668

这里解释一下htop命令mem的颜色,绿色 = 已用内存,蓝色 = 缓冲区,黄色/橙色 = 缓存。这里缓存比较多应该是我开机时间太长了缓存留存在内存中:105天。

可以用一个大文件作为swap分区

# 创建要作为swap分区的文件:增加1GB大小的交换分区,则命令写法如下,其中的count等于想要的块的数量(bs*count=文件大小)。
$ dd if=/dev/zero of=/root/swapfile bs=1M count=1024
# 格式化为交换分区文件:
$ mkswap /root/swapfile #建立swap的文件系统
# 启用交换分区文件:
$ swapon /root/swapfile #启用swap文件
# 使系统开机时自启用,在文件/etc/fstab中添加一行:
/root/swapfile swap swap defaults 0 0

image-20210823174308826

梳理一下硬件访问内存的流程:硬件从虚拟地址获取VPN(虚拟页面号),检查是否TLB命中,命中直接获取物理地址从内存中取回。不命中就根据虚拟地址的VPN和偏移量查找该页的页表项(PTE)得到物理内存地址来访问物理内存,并将其插入到TLB。目前的问题是页可能不在物理内存中,而是在交换空间中。所以需要一个在PTE中增加存在位来表示页是否在内存中。如果不在物理内存中,就会触发一个page fault来访问交换空间。

去硬盘上哪里寻找需要的页?PTE原本要放物理内存地址的,现在存在位为0,物理内存地址位没有意义了,就可以用相关的一些位来存放硬盘地址。完成后更新页表项和TLB。

动用交换空间是因为内存就不够用了,将swap上的页交换到内存上,内存满了怎么办?就需要交换出一些页。而交换策略至关重要。因为硬盘超慢,策略不好了一直在访问硬盘。

swap也不是内存满了才交换,而是设置有低水位线和高水位线,交换守护进程会负责将内存位置在水位线范围内。

交换机制是性能和价格的折衷,整个过程对进程透明,进程访问虚拟地址,得到需要的数据。区别只是速度快慢而已。

交换策略

早期内存金贵,交换策略非常关键。今天也很重要,swap能让你卡,而不是挂,现在一般也是固态了,访问速度比机械硬盘也提升了很多。

内存可以视为虚拟内存页的缓存,交换策略的目标就是要让cache miss最少。

最优替换策略

顾名思义,能达到总体未命中最少。方法:替换内存中最远将来才会被访问的页。这是理想化的,不可能知道。该方法可以作为比较其他策略性能的参照。

FIFO

队列,实现简单,无法确定页的重要性,一般。

随机

实现简单,性能看运气。

LRU

LRU(Least recently used,最近最少使用)。

交换策略的一个重要依据应该是之前的访问,你不应该删除一个经常访问的页。

可以用到的信息一个是频率,一个是访问的近期性。

相应的算法如LFU(Least frequently used,最不经常使用 )和LRU。

局部性:程序倾向于表现两种类型的局部,一是空间局部性,一个页被访问,相邻的页可能也会被访问,如遍历数组,另一个是时间局部性,近期访问的页可能一会也会访问,例如一些数据结构。

想要精确实现基于历史信息的算法,一种方法是每次访问页更新一些数据,如维护一个树,这样的记录和维护可能反而会影响性能。一种是硬件支持,硬件访问页时更新时间字段,需要替换页时简单扫描,但是扫描页太慢了。

太精确没有必要,差不多就可以。

近似LRU

硬件增加一个使用位。每次引用页,硬件将使用位置1,清除由OS负责。

时钟算法:循环列表,查找页的使用位,是1就清零,下一个;是零说明最近没有使用该页,替换掉。硬件设置访问,时钟循环列表保证时间。

脏页考虑

如果页被修改变成脏页,踢出它需要写回磁盘,代价很高。硬件应该再增加一个修改位,写入页时设置它。时钟算法就可以将脏页考虑在内。