操作系统学习之用C语言模拟CLOCK算法

本文介绍了CLOCK页面替换算法,它是FIFO和LRU算法的折衷,利用“免死金牌”考虑了程序局部性原理。通过C语言模拟了CLOCK算法的运行过程,展示了如何在页框满时进行页面置换。代码中,当扫描到有“免死金牌”的页框时,会重置其标志,没有“免死金牌”的页框则会被置换。博客还提供了代码解析和运行结果,帮助理解算法的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

CLOCK算法,顾名思义,时钟算法,是一个在FIFO和LRU的折衷算法,很符合我们的中庸之道,来学一学它折衷了哪些部分。

Buddy算法:操作系统学习之用C语言模拟伙伴(Buddy)算法
FIFO算法:操作系统学习之用C语言模拟FIFO算法
LRU算法:操作系统学习之用C语言模拟LRU算法
Clock算法:操作系统学习之用C语言模拟CLOCK算法
本源代码原创,转载请注明,同时由于本人才疏学浅,刚入门操作系统,如有错误敬请指教
本文原创,创作不易,转载请注明!!!
本文链接
个人博客:https://ronglin.fun/?p=205
PDF链接:见博客网站
优快云: https://blog.youkuaiyun.com/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=

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值