「算法精解_C语言描述」链表_循环链表实例 内存页帧置换(图解+实现)

来源:互联网 发布:smart forfour 知乎 编辑:程序博客网 时间:2024/05/29 19:26

在单链表的实例文章中介绍过如何使用单链表管理内存页帧的分配 使用单链表管理页帧 。但还有一个问题没有搞清楚,那就是当空闲页面的链表为空时,系统如何为其分配新的页帧呢?

为了解决这个问题,操作系统从物理内存中取出页面将其放入称为交换磁盘的磁盘空间中,以这种方式来释放页帧。操作系统采用页面转换算法来决定哪一个页帧在当前最适合释放。页面转换算法中的一个例子是第二次机会转换法,有时也称为时钟算法

一般情况下有很多进程可能在系统中同时运行,所有的进程都在争用物理内存资源。有此时候,甚至一个单独的进程就占用很大的地址空间,以至于它无法完全载入物理内存中。某些时候我们不得不面对必须去替换某些页面到交换磁盘的情况。那么,最适合操作系统替换的页面应该就是在未来最长的一段时间内都不会再次访问的那些页面,这才是最合理的。然而,由于我们无法预测未来,因此操作系统有时候会利用过去的表现作为一种对未来情况的合理假设,以此为依据去替换最近最少访问的那些页面。这种方法被称为最近最少使用算法(Least Recently Used),或LRU页面替换法

第二次机会置换法是实现LRU页面置换法的一种方式。它的工作方式是:维护一个当前存在于物理内存中的页面的循环链表。假设链表中的每个元素只存储一个页码和一个引用值(在实际中还会包含其他的信息),引用值要么为1要么为0。所有的页面初始引用值都设置为0。每当系统访问页面时(比如某个进程开始读或写某个页面),该页面的引用值就设置为1。

当需要某个页帧时,操作系统就使用它维护的循环链表以及引用值来判断哪些页面应该释放其页帧。为了确定这一点,开始遍历链表直到找到一个引用值为0的元素。当遍历每一个页面时,操作系统将页面的引用值从1重设回0。一旦它遇到一个引用值为0的元素它就找到了一个自从上次遍历链表以来都没有被系统访问过的页面,因此这个页面就是最近最少使用的页面。那么这个页面就在物理内存中和新的页面置换,新的页面被插入链表中原来页面的位置。如果自从算法上次运行以来,所有的页面都被访问过了,那么操作系统就完整地遍历了一次链表,此时就置换它开始的页面。

示例1 是关于这种页面置换算法的实现。函数replace_page接收唯一的参数current,current指向循环链表中的一个元素,该元素包含要开始搜索的页面(见图1)。当开始遍历链表时,该算法开始检测数据结构page中存储的reference成员,检测其值为1还是0.如果是1则重置该值为0,并开始遍历下一个页面;如果值为0,则找到了应该被替换的页面。最终,如果所有页面都被遍历过一次,根据循环链表的特性,算法将再次回到它刚开始遍历的页面。这时该页面的引用值为0(因为如果第一次遍历时遇到该页面,则其引用值应该已经重置为0),因此该页面就应该是待置换的页面。当函数返回时,current指向的页面就是搜索结束的位置。这个页面就是下一次当系统需要某个页帧时应该选择的页面。

循环链表的模型非常完美的解决了这个问题,因为它允许操作系统循环遍历所有的页面,而这正是算法所需要的。replace_page函数的运行时复杂度是O(n),这里n代表循环链表中的页面数量。在最坏的情况下,该算法可能需要遍历整个链表才能找到应该被置换的页面。


示例1: 第二次机会页面置换算法头文件

/*page.h*/#ifndef PAGE_H#define PAGE_H#include  "clist.h"/*Define a structure for information about pages.*/typedef struct page_{    int number;    int reference;}page;/*public interface*/int replace_page(CListElmt **current);#endif 

示例2 :  第二次机会页面置换算法的实现

/*page.c*/#include "clist.h"#include "page.h"int replace_page(CListElmt **current){    /*Cricle though the list of pages until one is found to replace.*/    while(((page *)(*current)->data)->reference != 0)    {        ((page *)(*current)->data)->reference = 0;        *current = clist_next(*current);    }        return ((page *)(*current)->data)->number;}




阅读全文
0 0
原创粉丝点击