前言
CLOCK算法,顾名思义,时钟算法,是一个在FIFO和LRU的折衷算法,很符合我们的中庸之道,来学一学它折衷了哪些部分。
Buddy算法:操作系统学习之用C语言模拟伙伴(Buddy)算法
FIFO算法:操作系统学习之用C语言模拟FIFO算法
LRU算法:操作系统学习之用C语言模拟LRU算法
Clock算法:操作系统学习之用C语言模拟CLOCK算法
本源代码原创,转载请注明,同时由于本人才疏学浅,刚入门操作系统,如有错误敬请指教
本文原创,创作不易,转载请注明!!!
本文链接
个人博客:https://ronglin.fun/?p=205
PDF链接:见博客网站
CSDN: https://blog.csdn.net/RongLin02/article/details/117632407
算法模拟
教科书原图
算法解释
先来看看课本上的解释。
时钟策略有很多的变种,最简单的时钟策略需要给每个页框关联一个使用位的附加位。当某页首次装入内存时,将该页框的使用位置为1;该页随后被访问时(在访问产生缺页中断后),其使用位也会置为1。对于页面置换算法,用于置换的候选页框集(当前进程:局部范围;整个内存:全局范围)被视为一个循环缓冲区,并有一个指针与之相关联,当一页被置换时,该指针被置为指向缓冲区中的下一个页框。需要置换一个页时,操作系统扫描缓冲区,查找使用位为 0的一个页框。每当遇到一个使用位为1的页框,操作系统就会将该位重置为0;若在这个过程开始时,缓冲区中所有页框的使用位均为0,则选择遇到的第一个页框置换;若所有页框的使用位均为1,则指针在缓冲区中完整地循环一周,把所有使用位都置为0,并且停留在最初的位置上,置换该页框的页。可见,该策略类似于FIFO,唯一不同的,在时钟策略中会跳过使用位为1的页框。这种策略称位时钟策略的原因是,我们可以把页框想象在一个环中。 ——操作系统-精髓与设计原理(第九版)P227
代码解释
教科书的解释太多了。简单说一下大概意思,就是当扫描的时候,还是用的FIFO,从头扫描到尾,但是不同的是,每个页框都有一个"免死金牌",当第一次扫描到的时候,如果有"免死金牌"就用掉金牌,如果没有则直接被替换。好处就是考虑到了程序的局部性原理,而且开销相比LRU小很多,只用维护"免死金牌"量就行了。
解释一下代码过程,当一个"页框"到来时 ,先找一遍,CLOCK_list中有没有,如果有,更新一下"免死金牌",如果没有,则开始执行时钟算法,从index指针开始扫描,若有"免死金牌"(flag)就用掉金牌(flag = 0),如果没有"免死金牌",则置换这一页。如果index到了队尾,就把其放置到开头。
源代码
#include<stdio.h>
#define MAX_NUM 3
#define MAX_NUM_PROC 512
//进程结构体
struct CList
{
int data;
int flag;
}CLOCK_list[MAX_NUM];
/*
12
2 3 2 1 5 2 4 5 3 2 5 2
*/
int main()
{
for(int i=0;i<MAX_NUM;i++)
{
CLOCK_list[i].data = 0;
CLOCK_list[i].flag = 0;
}
int n;
int a[MAX_NUM_PROC];
printf("请输入个数:");
scanf("%d",&n);
printf("请输入%d个非零数字:\n",n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
int index = 0;
for(int i=0;i<n;i++)
{
int exist =0;
for(int j=0;j<MAX_NUM;j++)
{
if(CLOCK_list[j].data == a[i])
{
CLOCK_list[j].flag =1;
exist = 1;
break;
}
}
if(!exist)
{
int full = 0;
for(;index<MAX_NUM;index++)
{
if(CLOCK_list[index].flag ==0)
{
full = 1;
CLOCK_list[index].data = a[i];
CLOCK_list[index].flag =1;
index++;
break;
}
else
{
CLOCK_list[index].flag =0;
}
}
if(index == MAX_NUM)
index = 0;
//如果满了,置换第一页
if(!full)
{
CLOCK_list[0].data = a[i];
CLOCK_list[0].flag =1;
index++;
}
}
printf("本次队列情况:");
for(int j=0;j<MAX_NUM;j++)
{
printf("%d",CLOCK_list[j].data);
if(CLOCK_list[j].flag == 1)
{
printf("*");
}
else
{
printf("#");
}
(j==MAX_NUM-1)?printf("\n"):printf(" ; ");
}
}
return 0;
}
输出解释
请输入个数:12
请输入12个非零数字:
2 3 2 1 5 2 4 5 3 2 5 2
本次队列情况:2* ; 0# ; 0#
本次队列情况:2* ; 3* ; 0#
本次队列情况:2* ; 3* ; 0#
本次队列情况:2* ; 3* ; 1*
本次队列情况:5* ; 3# ; 1#
本次队列情况:5* ; 2* ; 1#
本次队列情况:5* ; 2* ; 4*
本次队列情况:5* ; 2* ; 4*
本次队列情况:3* ; 2# ; 4#
本次队列情况:3* ; 2* ; 4#
本次队列情况:3* ; 2# ; 5*
本次队列情况:3* ; 2* ; 5*
*表示还有"免死金牌",#表示没有"免死金牌"了,结果和书上的一样,不在解释了。
总结
CLOCK算法是一个很有意思的算法,最开始想用一个循环双向链表表示的,但是循环双向链表维护起来比较麻烦,我就用一个数组来维护吧。=w=