操作系统:用C语言模拟先进先出的算法(FIFO)、最久未使用算法(LRU)、改进的Clock置换算法的命中率。

2.1 实验目的

  通过请求页面式存储管理中页面置换算法设计,了解存储技术的特点,掌握请求页式存储管理的页面置换算法。

2.2 实验内容

用程序实现生产者——消费者问题,将指令序列转换为用户虚存中的请求调用页面流。

具体要求:

  1. l页面大小为1K
  1. l用户内存容量为4页到40页
  1. l用户外存的容量为40k

在用户外存中,按每K存放10条指令,400条指令在外存中的存放方式为:

  1. l0-9条指令为第0页
  1. l10-19条指令为第1页

。。。。。

  1. l390-399条指令为第39页

按以上方式,用户指令可组成40页,通过随机数产生一个指令序列,共400个指令(0-399)。模拟请求页式存储管理中页面置换算法,执行一条指令,首先在外存中查找所对应的页面和页面号,然后将此页面调入内存中,模拟并计算下列三种算法在不同内存容量下的命中率(页面有效次数/页面流的个数):

1.先进先出的算法(FIFO)

2.最久未使用算法(LRU)

3.改进的Clock置换算法

提示

·随机指令的产生 :rand() 或srand()

·用户内存中页面控制结构采用链表

struct p_str{

int pagenum; /* 页号 */

int count; /* 访问页面的次数 */

struct p_str next; /* 下一指针 */

}p_str;

2.3算法描述

FIFO先入先出算法采用队列思想,先调入内存的页放在最前面,当内存存满时新的不同的页需要调入内存时,旧的页要进行依次出队,然后将新的页放入队列最后。

LRU最久未使用算法在使用时增加了一个时间time参数,当一个内存的页刚被调入或者访问时,time会归零,当在一次时间片内未使用时时间参数time++。当内存存满且有新的页调入内存时时,会在内存中挑选time最大的页进行删除,并将新的页填入。

改进Clock置换算法一共分四步,当内存存满且有新页调入时,先寻找A=0且M=0的进行替换,如果没有则寻找A=0且M=1进行替换,如果没有将所有内存中的页的A便为0,在重复以上两步进行内存中的新旧页替换。

2.4 实验结果(Linux虚拟机运行)

编译指令:g++ -o page page.cpp

运行指令:./page

根据数学计算可知,当内存页为40时,三种算法的命中率均为90及以上。

当内存页小于40时,三种算法在随机生成页时命中率是离散的

2.5 小结

本代码中FIFO采用队列并没有太大难度,而LRU相对FIFO仅是增加了一个时间变量用来选择置换的页,也就是说每次置换相对于FIFO要多出一个遍历求最大值的过程,也不能忘了在对链表进行增删的时候应该在遍历时遍历到length-1以此到达要删除结点的前一个结点,这样直接令前一结点的next=next->next,十分方便。代码中最难的就是改进Clock算法,其难就难在于多次进行链表遍历和增删所导致的结点为NULL或者爆内存的情况,因此最应该注意的是一共需要每次增删最多会遍历四次,所以在引用游标指针pp时应该在每次遍历完的时候重新让其等于begin也就是队首,这样才能保证代码不报错或者得出的测试概率错误。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#define maxsize 400	/*400访问次数*/
typedef struct p_str {
	int pagenum; /* 页号 */
	int count; /* 访问页面的次数 */
	int aa;/*访问位(Clock)*/
	int mm;/*修改位(Clock)*/
	int longtime;/*未使用的时间(LRU)*/
	struct p_str* next; /* 下一指针 */
}p_str;
int n;
void FIFO();
void LRU();
void Improve_Clock();

int main() {
	int m;
	srand((unsigned)time(NULL));
	scanf("%d %d", &n, &m); //输入内存容量和测试次数
	int i = m;
	while (m--) {
		printf("\n第%d次测试\n", i - m);
		//cout << endl << "第" << i - m << "次测试" << endl;
		FIFO();
		LRU();
		Improve_Clock();
	}
}

void FIFO() {
	double effective = 0;	/*有效访问次数*/
	int length = 0;		/*队列长度*/
	p_str* begin = (p_str*)malloc(sizeof(p_str));		/*创建头结点*/
	p_str* end = begin;		/*创建尾结点*/
	begin->count = -1; begin->pagenum = -1; begin->next = NULL;
	for (int i = 0; i < maxsize; i++) {	/*400次随机数测试*/
		int t = 0;
		int page = rand() % 400 / 10;
		p_str* pp = begin;
		for (int j = 0; j < length; j++) {		/*先遍历看内存是否有相同的页*/
			pp = pp->next;
			if (pp->pagenum == page) {		/*有则有效次数加一*/
				pp->count++;
				t = 1;
				effective++;
				break;
			}
		}
		if (t == 0) {		/*进行无效访问,即添加结点或替换节点*/
			if (length < n) {		/*内存未满,添加结点*/
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL;
				end->next = q;
				end = q;
				length++;
			}
			else {		/*内存已满,删除表头结点,新结点加到表尾*/
				begin->next = begin->next->next;
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL;
				end->next = q;
				end = q;
			}
		}
	}
	printf("在页面流个数为%d,内存容量为%d页的条件下,FIFO命中率为:%f %%\n", maxsize, n, (effective / 400) * 100);
	//cout << "在页面流个数为" << maxsize << ",内存容量为" << n << "页的情况下,FIFO命中率为:" << (effective / 400) * 100 << "%" << endl;
}

void LRU() {
	double effective = 0;	/*有效访问次数*/
	int length = 0;		/*队列长度*/
	p_str* begin = (p_str*)malloc(sizeof(p_str));	/*创建头尾结点*/
	p_str* end = begin;
	begin->count = -1; begin->pagenum = -1; begin->longtime = -1; begin->next = NULL;
	for (int i = 0; i < maxsize; i++) {		/*400次随机数测试*/
		int t = 0;
		int page = rand() % 400 / 10;
		p_str* pp = begin;
		for (int j = 0; j < length; j++) {		/*遍历内存看是否可以有效访问*/
			pp = pp->next;
			if (pp->pagenum == page) {
				pp->count++; pp->longtime = -1; t++; effective++; break;
			}
		}
		if (!t) {		/*无效访问*/
			if (length < n) {		/*添加结点*/
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL; q->longtime = -1;
				end->next = q;
				end = q;
				length++;
			}
			else {
				int max, maxtime = -1;		/*最久未访问结点位置,最久未访问时间*/
				pp = begin;
				for (int j = 0; j < length; j++) {		/*寻找最久未访问的结点*/
					pp = pp->next;
					if (pp->longtime > maxtime) {
						maxtime = pp->longtime;
						max = j;
					}
				}
				pp = begin;
				for (int j = 0; j < max - 1; j++) {		/*删除该结点*/
					pp = pp->next;
				}
				pp->next = pp->next->next;
				p_str* q = (p_str*)malloc(sizeof(p_str));	/*添加新结点*/
				q->count = 1; q->pagenum = page; q->next = NULL; q->longtime = -1;
				end->next = q;
				end = q;
			}
		}
		pp = begin;
		for (int j = 0; j < length; j++) {		/*所有未被访问节点时间加一*/
			pp = pp->next;
			pp->longtime++;
		}
	}
	printf("在页面流个数为%d,内存容量为%d页的条件下,LRU命中率为:%f %%\n", maxsize, n, (effective / 400) * 100);
	//cout << "在页面流个数为" << maxsize << ",内存容量为" << n << "页的情况下,LRU命中率为:" << (effective / maxsize) * 100 << "%" << endl;
}

void  Improve_Clock() {
	double effective = 0;	/*有效访问次数*/
	int length = 0;		/*队列长度*/
	p_str* begin = (p_str*)malloc(sizeof(p_str));		/*创建头尾结点*/
	p_str* end = begin;
	begin->count = -1; begin->pagenum = -1; begin->aa = -1; begin->mm = -1; begin->next = NULL;
	for (int i = 0; i < maxsize; i++) {
		int t = 0;
		int page = rand() % 400 / 10;
		int  m = rand() % 2;
		p_str* pp = begin;
		for (int j = 0; j < length; j++) {		/*尝试有效访问*/
			pp = pp->next;
			if (pp == NULL) {
				pp = end;
			}
			if (pp->pagenum == page) {
				pp->aa = 1; t++; effective++; break;
			}
		}
		if (!t) {
			if (length < n) {		/*添加结点*/
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL; q->longtime = -1; q->aa = 1; q->mm = m;
				end->next = q;
				end = q;
				length++;
			}
			else {
				int f = 0;
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL; q->longtime = -1; q->aa = 1; q->mm = m;
				p_str* pp = begin;
				for (int j = 0; j < length-1; j++) {
					if (pp->next->aa == 0 && pp->next->mm == 0) {		/*寻找A=0,M=0替换*/
						pp->next = pp->next->next;
						end->next = q;
						end = q;
						f = 1; break;
					}
					else {
						pp = pp->next;
					}
				}
				if (f)continue;
				else {
					pp = begin;
					for (int j = 0; j < length-1; j++) {
						if (pp->next->aa == 0 && pp->next->mm == 1) {		/*寻找A=0,M=1替换*/
							pp->next = pp->next->next;
							end->next = q;
							end = q;
							f = 1; break;
						}
						else {
							pp = pp->next;
						}
					}
				}
				if (f)continue;
				else {
					pp = begin;
					for (int j = 0; j < length; j++) {		/*所有结点A归零*/
						pp = pp->next;
						pp->aa = 0;
					}
				}
				pp = begin;
				for (int j = 0; j < length-1; j++) {
					if (pp->next->aa == 0 && pp->next->mm == 0) {	/*寻找A=0,M=0替换*/
						pp->next = pp->next->next;
						end->next = q;
						end = q;
						f = 1; break;
					}
					else {
						pp = pp->next;
					}
				}
				if (f)continue;
				else {
					pp = begin;
					for (int j = 0; j < length-1; j++) {
						if (pp->next->aa == 0 && pp->next->mm == 1) {	/*寻找A=0,M=1替换*/
							pp->next = pp->next->next;
							end->next = q;
							end = q;
							f = 1; break;
						}
						else {
							pp = pp->next;
						}
					}
				}
			}
		}
	}
	//cout << "在页面流个数为" << maxsize << ",内存容量为" << n << "页的情况下,优化Clock命中率为:" << (effective / maxsize) * 100 << "%" << endl;
	printf("在页面流个数为%d,内存容量为%d页的条件下,优化Clock命中率为:%f %%\n", maxsize, n, (effective / 400) * 100);
}

  • 6
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是使用 C 语言实现不同页面置换算法的示例代码: 1. 先进先出FIFO算法 ```c #include <stdio.h> int main() { int n, frames, hits = 0, faults = 0, index = 0, flag = 0; printf("Enter the number of pages: "); scanf("%d", &n); int reference_string[n]; printf("Enter the reference string: "); for(int i = 0; i < n; i++) { scanf("%d", &reference_string[i]); } printf("Enter the number of frames: "); scanf("%d", &frames); int frame[frames]; for(int i = 0; i < frames; i++) { frame[i] = -1; } for(int i = 0; i < n; i++) { flag = 0; for(int j = 0; j < frames; j++) { if(frame[j] == reference_string[i]) { hits++; flag = 1; break; } } if(flag == 0) { frame[index] = reference_string[i]; faults++; index++; if(index == frames) { index = 0; } } printf("Reference string: "); for(int j = 0; j <= i; j++) { printf("%d ", reference_string[j]); } printf("\n"); printf("Frames: "); for(int j = 0; j < frames; j++) { printf("%d ", frame[j]); } printf("\n"); } printf("Page faults: %d\n", faults); printf("Page hits: %d\n", hits); printf("Hit ratio: %f\n", (float)hits/n); return 0; } ``` 2. 最近最久使用LRU算法 ```c #include <stdio.h> int main() { int n, frames, hits = 0, faults = 0, min, index, flag; printf("Enter the number of pages: "); scanf("%d", &n); int reference_string[n]; printf("Enter the reference string: "); for(int i = 0; i < n; i++) { scanf("%d", &reference_string[i]); } printf("Enter the number of frames: "); scanf("%d", &frames); int frame[frames]; int counter[frames]; for(int i = 0; i < frames; i++) { frame[i] = -1; counter[i] = 0; } for(int i = 0; i < n; i++) { flag = 0; for(int j = 0; j < frames; j++) { if(frame[j] == reference_string[i]) { hits++; flag = 1; counter[j] = i; break; } } if(flag == 0) { faults++; min = counter[0]; index = 0; for(int j = 1; j < frames; j++) { if(counter[j] < min) { min = counter[j]; index = j; } } frame[index] = reference_string[i]; counter[index] = i; } printf("Reference string: "); for(int j = 0; j <= i; j++) { printf("%d ", reference_string[j]); } printf("\n"); printf("Frames: "); for(int j = 0; j < frames; j++) { printf("%d ", frame[j]); } printf("\n"); } printf("Page faults: %d\n", faults); printf("Page hits: %d\n", hits); printf("Hit ratio: %f\n", (float)hits/n); return 0; } ``` 3. 时钟(Clock算法 ```c #include <stdio.h> #include <stdlib.h> typedef struct { int page; int use_bit; } Frame; int main() { int n, frames, hits = 0, faults = 0, flag; printf("Enter the number of pages: "); scanf("%d", &n); int reference_string[n]; printf("Enter the reference string: "); for(int i = 0; i < n; i++) { scanf("%d", &reference_string[i]); } printf("Enter the number of frames: "); scanf("%d", &frames); Frame frame[frames]; for(int i = 0; i < frames; i++) { frame[i].page = -1; frame[i].use_bit = 0; } int pointer = 0; for(int i = 0; i < n; i++) { flag = 0; for(int j = 0; j < frames; j++) { if(frame[j].page == reference_string[i]) { hits++; frame[j].use_bit = 1; flag = 1; break; } } if(flag == 0) { faults++; while(frame[pointer].use_bit == 1) { frame[pointer].use_bit = 0; pointer = (pointer + 1) % frames; } frame[pointer].page = reference_string[i]; frame[pointer].use_bit = 1; pointer = (pointer + 1) % frames; } printf("Reference string: "); for(int j = 0; j <= i; j++) { printf("%d ", reference_string[j]); } printf("\n"); printf("Frames: "); for(int j = 0; j < frames; j++) { printf("%d ", frame[j].page); } printf("\n"); } printf("Page faults: %d\n", faults); printf("Page hits: %d\n", hits); printf("Hit ratio: %f\n", (float)hits/n); return 0; } ``` 4. 最不经常使用(LFU)算法 ```c #include <stdio.h> #include <stdlib.h> typedef struct { int page; int freq; } Frame; int main() { int n, frames, hits = 0, faults = 0, flag, min, index; printf("Enter the number of pages: "); scanf("%d", &n); int reference_string[n]; printf("Enter the reference string: "); for(int i = 0; i < n; i++) { scanf("%d", &reference_string[i]); } printf("Enter the number of frames: "); scanf("%d", &frames); Frame frame[frames]; for(int i = 0; i < frames; i++) { frame[i].page = -1; frame[i].freq = 0; } for(int i = 0; i < n; i++) { flag = 0; for(int j = 0; j < frames; j++) { if(frame[j].page == reference_string[i]) { hits++; flag = 1; frame[j].freq++; break; } } if(flag == 0) { faults++; min = frame[0].freq; index = 0; for(int j = 1; j < frames; j++) { if(frame[j].freq < min) { min = frame[j].freq; index = j; } } frame[index].page = reference_string[i]; frame[index].freq = 1; } printf("Reference string: "); for(int j = 0; j <= i; j++) { printf("%d ", reference_string[j]); } printf("\n"); printf("Frames: "); for(int j = 0; j < frames; j++) { printf("%d(%d) ", frame[j].page, frame[j].freq); } printf("\n"); } printf("Page faults: %d\n", faults); printf("Page hits: %d\n", hits); printf("Hit ratio: %f\n", (float)hits/n); return 0; } ``` 5. 最优(OPT)算法 ```c #include <stdio.h> #include <stdlib.h> int main() { int n, frames, hits = 0, faults = 0, max, index, flag; printf("Enter the number of pages: "); scanf("%d", &n); int reference_string[n]; printf("Enter the reference string: "); for(int i = 0; i < n; i++) { scanf("%d", &reference_string[i]); } printf("Enter the number of frames: "); scanf("%d", &frames); int frame[frames]; for(int i = 0; i < frames; i++) { frame[i] = -1; } int next[n]; for(int i = 0; i < n; i++) { next[i] = -1; for(int j = i + 1; j < n; j++) { if(reference_string[j] == reference_string[i]) { next[i] = j; break; } } } for(int i = 0; i < n; i++) { flag = 0; for(int j = 0; j < frames; j++) { if(frame[j] == reference_string[i]) { hits++; flag = 1; break; } } if(flag == 0) { faults++; max = -1; index = -1; for(int j = 0; j < frames; j++) { if(next[frame[j]] == -1) { index = j; break; } if(next[frame[j]] > max) { max = next[frame[j]]; index = j; } } frame[index] = reference_string[i]; } printf("Reference string: "); for(int j = 0; j <= i; j++) { printf("%d ", reference_string[j]); } printf("\n"); printf("Frames: "); for(int j = 0; j < frames; j++) { printf("%d ", frame[j]); } printf("\n"); } printf("Page faults: %d\n", faults); printf("Page hits: %d\n", hits); printf("Hit ratio: %f\n", (float)hits/n); return 0; } ``` 以上是使用 C 语言实现不同页面置换算法的示例代码,每个算法实现方式略有不同,但都是基于相同的基本思想。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淬炼之火

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值