第一篇:操作系统-课程设计报告-处理机调度程序
操作系统
课程设计报告
学校:广州大学
学院:计算机科学与教育软件学院 班级:计算机127班 课题:处理机调度程序
任课老师:陶文正、陈文彬
姓名:黄俊鹏
学号:1200002111 班内序号:27 成绩:
日期:2015年1月6日
一、设计目的
在多道程序和多任务系统中,系统内同时处于就绪状态的进程可能有若干个。也就是说能运行的进程数大于处理机个数。为了使系统中的进程能有条不紊地工作,必须选用某种调度策略,选择一进程占用处理机。要求学生设计一个模拟处理机调度算法,以巩固和加深处理机调度的概念。
二、设计要求
1)进程调度算法包括:时间片轮转法,短作业优先算法,动态优先级算法。2)可选择进程数量
3)本程序包括三种算法,用C语言实现,执行时在主界面选择算法(可用函数实现)(进程数,运行时间,优先数由随机函数产生)执行,显示结果。
三、设计思路及算法思想
1.界面菜单选项
一级菜单提供2个选项: ① 自动生成进程数量 ② 手动输入所需进程数量
一级菜单选择完毕后进入二级菜单: ① 重新生成进程 ② 时间片轮转法 ③ 短作业优先算法 ④ 动态优先级算法 ⑤ 退出程序
2.调度算法
程序所用PCB结构体
需要用到的进程结构体如上图所示
1)时间片轮转法
主要是设置一个当前时间变量,curTime和时间片roundTime。
遍历进程组的时候,每运行一个进程,就把curTime += roundTime。进程已运行时间加roundTime
2)短作业优先算法
遍历进程组,找到未运行完成并且运行时间最短的进程,让它一次运行完成,如此往复,直到所有进程都运行完成为止。
3)动态优先级算法
做法跟短作业优先算法类似,此处主要是比较进程的优先数,优先级高者,先执行。直到全部执行完毕。当一个进程运行完毕后,适当增减其余进程的优先数,以达到动态调成优先级的效果。
3.程序流程图
四、运行截图
1)启动后输入5,生成5个进程
2)输入1,选择时间片轮转法。
自动输出结果,分别是时间片为1和4的结果
3)输入2,选择短作业优先算法
4)输入3,选择动态优先级算法
5)输入0,重新生成进程,再输入3,生成3个进程,选择2.短作业优先算法
6)输入q,退出
五、心得体会
通过这次实验,让我对操作系统的进程调度有了更进一步的了解。这个实验的模拟程度跟真实系统相比只是冰山一角,由此可见操作系统是何其复杂的软件产品,仅进程调度就有那么丰富和内涵的知识需要掌握。
但是再复杂的系统,都是由小部件构成的。古语云:不积跬步,无以至千里。不积小流,无以成江海。掌握这些基础的知识,可以为以后打下扎实的基础。
六、附录(源代码)
//
// main.c
// ProcessDispatch //
// Created by Jeans on 1/5/15.// Copyright(c)2015 Jeans.All rights reserved.//
#include
//最小进程数
#define MIN_PROCESS //最大进程数
#define MAX_PROCESS
//最小优先数
#define MIN_PRIORITY
0 //最大优先数
#define MAX_PRIORITY
//最小运行时间
#define MIN_RUNNING_TIME
//最大运行时间
#define MAX_RUNNING_TIME
typedef struct PCB{
char name;
//进程名
int priority;
//优先数
int runningTime;
//运行时间
int arriveTime;
//到达时间
int beginTime;
//开始时间
int finishTime;
//完成时间
int cyclingTime;
//周转时间
double weigthCyclingTime;//带权周转时间
int hadRunTime;
//已经运行时间
int finish;
//是否完成 }PCB;//获取随机数
int GetRandomNumber(int min,int max){
return arc4random()%(max-min)+ min;}
//初始化PCB组
void InitPCBGroup(PCB p[],int num){
char name = 'A';
for(int i = 0;i < num;i++){
p[i].name = name;
p[i].priority = GetRandomNumber(MIN_PRIORITY, MAX_PRIORITY);
p[i].runningTime = GetRandomNumber(MIN_RUNNING_TIME,MAX_RUNNING_TIME);
name++;
} }
void PrintResult(PCB p[],int num){
double avgCycTime = 0,avgWeiCycTime = 0;
printf(“|进程名
到达时间
运行时间
开始时间
完成时间
周转时间
带权周转时间
优先数
|n”);
for(int i = 0;i < num;i++){
printf(“|%3c
%-4d
%-4d
%-4d
%-4d
%-4d
%-6.2f
%-4d|n”,p[i].name,p[i].arriveTime,p[i].runningTime,p[i].beginTime,p[i].finishTime,p[i].cyclingTime,p[i].weigthCyclingTime,p[i].priority);
avgCycTime += p[i].cyclingTime;
avgWeiCycTime += p[i].weigthCyclingTime;
//还原
p[i].arriveTime = 0;
p[i].beginTime = 0;
p[i].finishTime = 0;
p[i].cyclingTime = 0;
p[i].weigthCyclingTime = 0;
p[i].hadRunTime = 0;
p[i].finish = 0;
}
avgWeiCycTime /= num;
avgCycTime /= num;
printf(“平均周转时间:%.2f
平均带权周转时间:%.2fn”,avgCycTime,avgWeiCycTime);} //时间片轮转法
void RealRoundRobin(PCB p[],int num,int roundTime){
printf(“nn-----------------------------时间片:%d------n”,roundTime);
int finishNum = 0;
int curTime = 0;
while(finishNum!= num){
for(int i = 0;i < num;i++){
if(p[i].finish)continue;
//开始时间
if(p[i].beginTime == 0 && i!= 0){
p[i].beginTime = curTime;
}
//已经完成
if(p[i].hadRunTime + roundTime >= p[i].runningTime){
p[i].finishTime = curTime + p[i].runningTimep[i].arriveTime;
p[i].weigthCyclingTime = p[i].cyclingTime/(double)p[i].runningTime;
p[i].finish = 1;
finishNum ++;
curTime += p[i].runningTimep[min].arriveTime;
p[min].weigthCyclingTime = p[min].cyclingTime/(double)p[min].runningTime;
p[min].finish = 1;
finishNum++;
curTime = p[min].finishTime;
}
PrintResult(p, num);}
//动态优先级算法
void DynamicPriorityFirst(PCB p[],int num){
printf(“nn-----------------------------动态优先级算法--n”);
int finishNum = 0;
int curTime = 0;
while(finishNum!= num){
int min = 0;
//查找优先级最高下标
for(int i = 1;i < num;i++){
if(p[i].finish == 0 && p[min].priority >= p[i].priority)
min = i;
else if(p[i].finish == 0 && p[min].finish == 1)
min = i;
}
p[min].beginTime = curTime;
p[min].hadRunTime = p[min].runningTime;
p[min].finishTime = p[min].beginTime + p[min].runningTime;
p[min].cyclingTime = p[min].finishTime-p[min].arriveTime;
p[min].weigthCyclingTime = p[min].cyclingTime/(double)p[min].runningTime;
p[min].finish = 1;
finishNum++;
curTime = p[min].finishTime;
}
PrintResult(p, num);}
int main(int argc, const char * argv[]){
PCB pcbGroup[30];
//pcb数组
int processNum = 0;//进程数
while(1){
//选择进程数量
while(1){
if(processNum!= 0)
break;
printf(“n----------n”);
printf(“当前默认进程数范围%d--%dn”,MIN_PROCESS,MAX_PROCESS);
printf(“1)输入0可随机生成进程数目n2)输入%d-%d范围内数字,回车,可生成指定数目进程n>>>>>>”,MIN_PROCESS,MAX_PROCESS);
int num = 0;
scanf(“%d”,&num);
if(num == 0){
processNum = GetRandomNumber(MIN_PROCESS, MAX_PROCESS);
break;
}else{
if((num >= MIN_PROCESS)&&(num <= MAX_PROCESS)){
processNum = num;
InitPCBGroup(pcbGroup,processNum);
break;
}else
printf(“n输入有误,请重新输入.n”);
}
}
//选择算法
printf(“n-----------------------------请输入对应选项序号-----------------------------n”);
printf(“0.重新生成进程 | 1.时间片轮转法 | 2.短作业优先算法 | 3.动态优先级算法 | q.退出n>>>>>>”);
char ch;
while((ch = getchar())== 'n');
switch(ch){
case '0'://0 重新生成进程
processNum = 0;break;
case '1'://1 时间片轮转法
RoundRobin(pcbGroup, processNum);break;
case '2'://2 短作业优先算法
ShortestJobFirst(pcbGroup, processNum);break;
case '3'://3 动态优先级算法
DynamicPriorityFirst(pcbGroup,processNum);break;
case 'q'://q 退出
exit(0);
default:
break;
}
}
return 0;}
第二篇:操作系统 单处理机系统的进程调度
一.实验内容描述
1.目的
(1)了解Windows内存管理器(2)理解Windows的地址过程 2.内容
任意给出一个虚拟地址,通过WinDbg观察相关数据并找到其物理地址
二.理论分析
Windows采用页式虚拟存储管理技术管理内存,页面是硬件级别上的最小保护单位 1.Windows内存管理器
Windows的内存管理主要由Windows执行体中的虚存管理程序负责,并由环境子系统负责,并由环境子系统负责与具体API相关的一些用户态特性的实现。虚存管理程序是Windows中负责内存管理的那些子程序和数据结构的集合 内存管理器的主要任务是:
地址变换:将一个进程的虚拟地址空间转译为物理内存地址
交换:当内存不足时,将内存中的有些内容转移到磁盘上,并且以后还要再次将这些内容读回
2.Windows内存管理策略
Windows采用页式虚拟存储管理技术管理内存,页面是硬件级别上最小的保护单位。根据硬件的体系结构不同,页面尺寸被分为两种,大页面和小页面。X86系统下小页面为4KB,大页面为4MB。大页面的优点是:当引用同一页面内其他数据时,地址转移的速度会很快。不过使用大页面通常要较大的内存空间,而且必须用一个单独的保护项来映射,因此可能会造成出现错误而不引发内存访问违例的情况。通常PC机都为小页面 3.Windows虚拟地址空间布局 x86结构下的布局方式:
默认情况下,32位Windows系统中每个用户进程可以占有2GB的私有地址空间。操作系统占有另外的2GB 2GB用户的进程地址空间布局如表:
2GB的系统地址空间布局如同:
3.虚拟地址转译
地址转译是指将进程的虚拟地址空间映射到实际物理页面的过程。x86系统中地址转译过程如图:
关键数据结构如下: 页目录:每个进程都有一个页目录,它是内存管理器为了映射进程中所有的页表位置而创建的一个页面。进程也目录的地址被保存在内核进程快KPROCESS中,在x86系统上,它被映射到虚拟地址0xC0300000,当一个进程正在执行时,CPU可以通过寄存器CR3知道该进程页目录的位置。页目录由目录项(PDE)构成,每个PDE长4字节,描述了该进程中所有可能的页表的状态和位置。其格式和PTE类似。x86系统上,要描述完整的4GB虚拟地址空间,需要1024个页表。因此映射这些页表的进程页目录需包含1024个PDE,恰好占用一个页面。
页表:进程的页目录项指向页表。每个页表占用一个页面,由1024项PTE组成。一个有效的PTE大小为4字节,包含两个主域:数据所在的物理页面的页面帧编号(PNF)或者内存中一个页面的物理地址的PFN;一些描述该页面状态和保护属性的标志。
虚拟地质结构:x86系统上,一个32位虚拟地址被解释为三个单独的部分,页目录索引、页表索引和字节索引。由于页目录项有1024个,因此页目录索引为10位;一个也表中含有1024个PTE。因此页表索引也为10位,字节索引为12位,正好表示一页(4KB)内容
三.实验步骤及结果
1.查找页目录首地址
以程序WG.exe作为观测对象。
启动WinDbg到内核调试模式,运行程序WG.exe。终断目标机运行,输入命令:kd>!process
发现WG.exe进程正处于运行状态 输入命令:
在KPROCESS中名为DirectoryTableBase的域,对应值为0x9fa6000,即WG.exe进程页目录的物理地址 查看CR3寄存其中的内容,输入命令:
CR3寄存其中的值和KPROCESS中记录的页目录基址相同。这是因为在CPU切换执行任务时,其内容要更新为当前进程的页目录基址。2.地址转译过程
假设给定的虚拟地址为0x401001 输入命令:
可以看到:
PDE的虚拟地址为C0300004.PTE的虚拟地址为C0001004 最后一行信息“pfn 9e4a---DA--UWEV”表示PDE中的具体内容,9e4a是给定虚拟地址所在页表在内存中对应的物理页号,“---DA—UWEV”是标志信息,“pfn a173----A--UREV”表示PTE中的具体内容,a173是数据页装入内存的物理页号。
将数据页对应的物理页号a173加上业内索引(0x1)即可得到虚拟地址0x401001的物理地址
3.观察系统页表
给定观测虚拟地址为0x80001001 输入命令:
当前正在执行的进程是:WG.exe 输入命令:
得到PDE为C0300800,其对应的物理页号为3b 继续让目标机运行,启动A.exe,然后中断目标机运行。输入命令:
当前正在执行的进程为A.exe 输入命令:
PDE信息和对应的物理页号与前面观测到的相同
四.结论
1.数据页对应的物理页号加上相应业内索引即可得到虚拟地址的物理地址 2.不同的进程页目录都指向了相同的系统表页
五.心得体会
在这次上机实验,通过对WinDbg和VPc的调试运用,我熟悉了Windows内存管理器的结构,也认知到Windows如何进行地址转译和转换。对相关的知识也进行了温习,更牢的掌握了相关知识。当然这些还远远不够,我以后还要继续不断努力,去学习了解掌握操作系统的各方面知识。
附录:
1.A.exe代码
#include
#define N 1
HANDLE mutexSemaphore;HANDLE synchSemaphore_1;HANDLE synchSemaphore_2;
HANDLE mutexDisplay;
void Display(char*str,int delayTime){ if(WaitForSingleObject(mutexDisplay,INFINITE)==WAIT_OBJECT_0){ printf(“%snn”,str);ReleaseMutex(mutexDisplay);Sleep(delayTime);} }
void useTime(double limit){ for(double i=0;i<=limit;i+=0.001);}
void CreateProduct(){ Display(“Creating a production...”,0);useTime(200000);Display(“Creating finished.”,100);}
void PutProduct(){ Display(“Putting a production...”,0);useTime(150000);Display(“Putting finished”,100);}
void GetProduct(){ Display(“Getting a production...”,0);useTime(100000);Display(“Getting finished.”,100);}
void ConsumeProduct(){ Display(“Cosuming a production...”,0);useTime(100000);Display(“Cosuming finished.”,100);}
void Producer(){ while(true){ CreateProduct();
if(WaitForSingleObject(synchSemaphore_1,INFINITE)==WAIT_OBJECT_0){
if(WaitForSingleObject(mutexSemaphore,INFINITE)==WAIT_OBJECT_0){ PutProduct();ReleaseSemaphore(mutexSemaphore,1,NULL);} ReleaseSemaphore(synchSemaphore_2,1,NULL);} } }
void Consumer(){ while(true){
if(WaitForSingleObject(synchSemaphore_2,INFINITE)==WAIT_OBJECT_0){
if(WaitForSingleObject(mutexSemaphore,INFINITE)==WAIT_OBJECT_0){ GetProduct();ReleaseSemaphore(mutexSemaphore,1,NULL);} ReleaseSemaphore(synchSemaphore_1,1,NULL);} ConsumeProduct();} }
int main(){ HANDLE thread[2];DWORD threadID[2];
synchSemaphore_1=CreateSemaphore(NULL,N,N,NULL);synchSemaphore_2=CreateSemaphore(NULL,0,N,NULL);mutexSemaphore=CreateSemaphore(NULL,1,1,NULL);
mutexDisplay=CreateMutex(NULL,FALSE,NULL);
printf(“Program start.Please use WinDbg to observe main thread.nPress any key to continue...n”);getchar();
thread[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Producer),NULL,CREATE_SUSPENDED,&threadID[0]);printf(“A producer was created.Please use WinDbg to observe producer thread.nPress any key to continue...n”);getchar();
thread[1]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consumer),NULL,CREATE_SUSPENDED,&threadID[1]);printf(“A Consumer was created.Please use WinDbg to observe Consumer thread.nPress any key to continue...n”);getchar();
printf(“Please select:n[1]Make producer thread runn[2]Make Consumer thread runn”);bool flag=true;bool flag_1=true,flag_2=true;int count=0;while(flag){ if(getchar()=='1'&&flag_1){ ResumeThread(thread[0]);count++;flag_1=false;} else if(getchar()=='2'&&flag_2){ ResumeThread(thread[1]);count++;flag_2=false;} if(count==2)flag=false;} WaitForMultipleObjects(1,thread,TRUE,INFINITE);
return 0;}
2.WG.exe代码: #include
int main(){ int a=0;printf(“I'm Wangn”);while(true){a++;} }
第三篇:操作系统课程设计-磁盘调度算法
1.实验题目:
磁盘调度算法。
建立相应的数据结构;
在屏幕上显示磁盘请求的服务状况;
将一批磁盘请求的情况存磁盘文件,以后可以读出并重放; 计算磁头移动的总距离及平均移动距离; 支持算法:FIFO、SSTF、SCAN、CSCAN;
2.设计目的:
调度磁盘I/O请求服务,采用好的方式能提高访问时间和带宽。本实验通过编程对磁盘调度算法的实现,加深对算法的理解,同时通过用C++语言编写程序实现这些算法,并在windos平台上实现,更好的掌握操作系统的原理以及实现方法,提高综合运用专业课知识的能力。
3.任务及要求
3.1 设计任务
编程实现下述磁盘调度算法,并求出每种算法的平均寻道长度:
1、先来先服务算法(FCFS)
2、最短寻道时间算法(SSTF)
3、扫描算法(SCAN)
4、循环扫描算法(CSCAN)
3.2 设计要求
对用户指定的磁盘调度请求序列,基于以上四种算法,实现各自的调度顺序并输出,同时计算出各种算法下的平均寻道长度。
4.算法及数据结构
4.1算法的总体思想
queue[n] 为请求调度序列,diskrode为磁盘磁道数,headstarts为正在调度的磁道
①先来先服务算法(FCFS)按queue[n]数组的顺序进行磁盘调度,将前一个调度磁道与下一个调度磁道的差值累加起来,得到总的寻道长度,再除以n得到平均寻道长度。
②最短寻道时间优先算法(SSTF)将queue[n]进行由小到大的排序,首先定位当前调度磁headstarts在queue[n]的位置,通过循环语句找出离起始磁头最短的位置。
③扫描算法(SCAN)
将queue[n]进行由小到大的排序,首先定位当前调度磁headstarts在queue[n]的位置,然后在此位置按给定的方向遍历queue[n],当道端点(queue[0]或queue[n-1])时,再在定位处反向遍历到另一端。当调度磁道不在queue端点时,总的寻道长度为为前一个磁道与后一个磁
道差值的累加,当到达端点且queue[n]未全调度时,总寻道长度加上端点值再加上下一个调度磁道的值,再按前面的算法进行,直到磁道全部都调度完毕,得到总的寻道长度,除以n得到平均寻道长度。
④循环扫描算法(CSCAN)将queue[n]进行由小到大的排序,首先定位当前调度磁headstarts在queue[n]的位置,然后在此位置按给定的方向遍历queue[n],当道端点(queue[0]或queue[n-1])时,反向到另一端点再以此方向进行遍历,直到queue[n]中所有都调度完。当调度磁道不在queue端点时,总的寻道长度为为前一个磁道与后一个磁道差值的累加,当到达端点且queue[n]未全调度时,总寻道长度加上端点值再加上磁盘磁道总长度,再加上下一个调度磁道的值,再按前面的算法进行,直到磁道全部都调度完毕,得到总的寻道长度,除以n得到平均寻道长度。
5、源代码:
#include 1、先来先服务算法(FCFS)**********”< cout<<“****** 2、最短寻道时间优先算法(SSTF)**********”< cout<<“****** 3、扫描算法(SCAN)**********”< cout<<“****** 4、循环扫描算法(CSCAN)**********”< cout<<“****** 5、退出 **********”< /*======================初始化序列=======================*/ void init(int queue[],int queue_copy[],int n){ int i;for(i=0;i //对当前正在执行的磁道号进行定位,返回磁道号小于当前磁道中最大的一个 int fix(int queue[], int n, int headstarts){ int i =0;while(i /* ====================以下是FCFS算法==================*/ void FCFS(int queue[],int n,int diskrode,int headstarts)//queue是请求调度序列,n为其个数,diskroad为磁盘磁道数,headstarts为正在调度的磁道 { cout<<“************以下为FCFS调度算法***********”< /*=====================SSTF算法====================*/ void SSTF(int queue[], int n, int diskrode, int headstarts){ int k=1;int l,r;int i,j,count=0;queue =bubble(queue,n);cout<<“************以下为SSTF调度算法***********”< -headstarts)){ cout< /*======================以下是SCAN算法====================*/ void SCAN(int queue[], int n, int diskrode, int headstarts){ int direction, i, fixi;cout<<“***********以下是SCAN调度算法*************”< /*======================以下是CSCAN算法====================*/ void CSCAN(int queue[],int n,int diskrode,int headstarts){ int direction,i,fixi;cout<<“***********以下是CSCAN调度算法*************”< void main(){ int n, i, diskrode, headstarts;//n表示调度磁盘请求序列queue的长度,diskrode表示磁盘磁道的个数,headstarts表示目前正在调度的磁道; cout<<“请输入磁盘的总磁道数:”< if(menux ==2)SSTF(queue,n,diskrode,headstarts); if(menux ==3)SCAN(queue,n,diskrode,headstarts);if(menux ==4)CSCAN(queue,n,diskrode,headstarts);if(menux ==5)cout<<“程序结束,谢谢使用!”< 沈阳理工大学课程设计专用纸 Noi 目 录 1 课程设计目的及要求……………………………………………………错误!未定义书签。2 相关知识…………………………………………………………………错误!未定义书签。3 题目分析…………………………………………………………………2 4 概要设计…………………………………………………………………2 4.1 先来先服务(FCFS)的设计思想……………………………….2 4.2 最短寻道时间优先调度(SSTF)的设计思想…………………..2 4.3 扫描算法(SCAN)的设计思想…………………………………2 4.4 循环扫描(CSCAN)的设计思想………………………………..2 5 代码及流程………………………………………………………………3 5.1 流程图……………………………………………………………...3 5.2 源代码……………………………………………………………...8 6 运行结果…………………………………………………………………16 7 设计心得…………………………………………………………………19 参考文献…………………………………………………………………………19 沈阳理工大学 沈阳理工大学课程设计专用纸 No1 1 课程设计目的及要求 设计目的:加深对操作系统原理的进一步认识,加强实践动手能力和程序开发能力的培养,提高分析问题解决问题的能力,培养合作精神,以巩固和加深磁盘调度的概念。操作系统是一门工程性很强的课程,它不仅要求学生掌握操作系统的工作原理和理论知识,也要求学生的实际动手能力,以加深对所学习内容的理解,使学生熟练地掌握计算机的操作方法,使用各种软件工具,加强对课程内容的理解。这次课程设计,就是通过模拟磁臂调度来加深对操作系统中磁臂调度概念的理解。使学生熟悉磁盘管理系统的设计方法;加深对所学各种磁盘调度算法的了解及其算法的特点。 设计要求:编程序实现下述磁盘调度算法,并求出每种算法的平均寻道长度;要求设计主界面可以灵活选择某算法,且以下算法都要实现 1、先来先服务算法(FCFS) 2、最短寻道时间优先算法(SSTF) 3、扫描算法(SCAN) 4、循环扫描算法(CSCAN)相关知识 数据结构:数组 now:当前磁道号; array[]:放置磁道号的数组; void FCFS(int array[],int m)先来先服务算法(FCFS)void SSTF(int array[],int m)最短寻道时间优先算法(SSTF)void SCAN(int array[],int m)扫描算法(SCAN)void CSCAN(int array[],int m)循环扫描算法(CSCAN)磁盘调度:当有多个进程都请求访问磁盘时,采用一种适当的驱动调度算法,使各进程对磁盘的平均访问(主要是寻道)时间最小。目前常用的磁盘调度算法有:1)闲来先服务2)最短寻道时间优先3)扫描算法4)循环扫描算法等 沈阳理工大学 沈阳理工大学课程设计专用纸 No2 3 题目分析 选择一个自己熟悉的计算机系统和程序设计语言模拟操作系统基本功能的设计方法及其实现过程 完成各分项功能。在算法的实现过程中,要求可决定变量应是动态可变的;同时模块应该有一个合理的输出结果。具体可参照实验的程序模拟.各功能程序要求自行编写程序实现,不得调用现有操作系统提供的模块或功能函数。磁盘调度程序模拟。先来先服务调度算法.最短寻道时间优先调度,循环(SCAN)调度算法。程序设计语言自选,最终以软件(含源代码以及执行程序)和设计报告的形式提交课程设计结果.。磁盘调度让有限的资源发挥更大的作用。在多道程序设计的计算机系统中,各个进程可能会不断提出不同的对磁盘进行读/写操作的请求。由于有时候这些进程的发送请求的速度比磁盘响应的还要快,因此我们有必要为每个磁盘设备建立一个等待队列。概要设计 1.先来先服务(FCFS)的设计思想 即先来的请求先被响应。FCFS策略看起来似乎是相当“公平”的,但是当请求的频率过高的时候FCFS策略的响应时间就会大大延长。FCFS策略为我们建立起一个随机访问机制的模型,但是假如用这个策略反复响应从里到外的请求,那么将会消耗大量的时间。为了尽量降低寻道时间,看来我们需要对等待着的请求进行适当的排序,而不是简单的使用FCFS策略。这个过程就叫做磁盘调度管理。有时候fcfs也被看作是最简单的磁盘调度算法。 2.最短寻道时间优先调度(SSTF)的设计思想 最短时间优先算法选择这样的进程。要求访问的磁道,与当前磁头所在的磁道距离最近,以使每次的寻道时间最短。 3.扫描算法(SCAN)的设计思想 扫描(SCAN)调度算法:该算法不仅考虑到欲访问 的磁道与当前磁道间的距离,更优先考虑的是磁头当前的移动方向。例如,当磁头正在自里向外移动时,SCAN算法所考虑的下一个访问对象,应是其欲访问的磁道,既在当前磁道之外,又是距离最近的。这样自里向外的访问,直至再无更外的磁道需要访问时,才将磁道换向自外向里移动。这时,同样也是每次选择这样的进程来调度,也就是要访问的当前位置内距离最近者,这样,磁头又逐步地从外向里移动,直至再无更里面的磁道要访问,从而避免了出现“饥饿”现像。 4.循环扫描(CSACN)的设计思想 循环扫描(CSCAN)算法:当磁头刚从里向外移动而越过了某一磁道时,恰好又有一进程请求访问此磁道,这时,该里程就必须等待,为了减少这种延迟,CSCAN算法规定磁头单向移动,而本实验过程中我们所设计的是磁头从里向外移动,而从外向里移动时只须改方向而已,本实验未实现。但本实验已完全能演示循环扫描的全过程。 沈阳理工大学 沈阳理工大学课程设计专用纸 No3 5 代码及流程 1.先来先服务(FCFS) 图 1—1 FCFS的流程图 沈阳理工大学 沈阳理工大学课程设计专用纸 No4 2.最短寻道时间优先调度(SSTF) 图1—2 SSTF的流程图 沈阳理工大学 沈阳理工大学课程设计专用纸 No5 3.扫描算法(SCAN) 图1—3 SCAN的流程图 沈阳理工大学 沈阳理工大学课程设计专用纸 No6 4.循环扫描(CSCAN) 图1—4 CSCAN的流程图 沈阳理工大学 沈阳理工大学课程设计专用纸 No7 图1—5 主函数的流程图 沈阳理工大学 沈阳理工大学课程设计专用纸 No8 源代码: #include“stdio.h” #include“stdlib.h” //#include“iostream.h” #define maxsize 100 //定义最大数组域 //先来先服务调度算法 void FCFS(int array[],int m){ int sum=0,j,i;int avg;printf(“n FCFS调度结果: ”);for(i=0;i } avg=sum/(m-1);//计算平均寻道长度 printf(“n 移动的总道数: %d n”,sum);printf(“平均寻道长度: %d n”,avg);} //最短寻道时间优先调度算法 void SSTF(int array[],int m){ int temp;int k=1;int now,l,r;int i,j,sum=0;int avg;for(i=0;i 沈阳理工大学 沈阳理工大学课程设计专用纸 No9 array[i]=array[j];array[j]=temp;} } } for(i=0;i for(i=m-1;i>=0;i--)//将数组磁道号从大到小输出 printf(“%d ”,array[i]);sum=now-array[0];//计算移动距离 } else if(array[0]>=now)//判断整个数组里的数是否都大于当前磁道号 { for(i=0;i printf(“%d ”,array[l]);sum+=now-array[l];//计算移动距离 now=array[l];l=l-1;} else 沈阳理工大学 沈阳理工大学课程设计专用纸 No10 { printf(“%d ”,array[r]);sum+=array[r]-now;//计算移动距离 now=array[r];r=r+1;} } if(l=-1){ for(j=r;j printf(“%d ”,array[j]);} sum+=array[m-1]-array[0];//计算移动距离 } else { for(j=l;j>=0;j--){ printf(“%d ”,array[j]);} sum+=array[m-1]-array[0];//计算移动距离 } } avg=sum/m;printf(“n 移动的总道数: %d n”,sum);printf(“平均寻道长度: %d n”,avg);} //扫描算法 void SCAN(int array[],int m)//先要给出当前磁道号和移动臂的移动方向 { int temp;int k=1;int now,l,r,d;int i,j,sum=0;int avg;for(i=0;i 沈阳理工大学 沈阳理工大学课程设计专用纸 No11 { temp=array[i];array[i]=array[j];array[j]=temp;} } } for(i=0;i printf(“n SCAN调度结果: ”);for(i=m-1;i>=0;i--){ printf(“%d ”,array[i]);//将数组磁道号从大到小输出 } sum=now-array[0];//计算移动距离 } else if(array[0]>=now)//判断整个数组里的数是否都大于当前磁道号 { printf(“n SCAN调度结果: ”);for(i=0;i 沈阳理工大学 沈阳理工大学课程设计专用纸 No12 { for(j=l;j>=0;j--){ printf(“%d ”,array[j]);} for(j=r;j //循环扫描算法 void CSCAN(int array[],int m){ int temp;int k=1;int now,l,r,d;int i,j,sum=0;int avg;for(i=0;i 沈阳理工大学 沈阳理工大学课程设计专用纸 No13 { temp=array[i];array[i]=array[j];array[j]=temp;} } } for(i=0;i printf(“n CSCAN调度结果: ”);for(i=0;i printf(“%d ”,array[i]);//将磁道号从小到大输出 } sum=now-array[0]+array[m-1];//计算移动距离 } else if(array[0]>=now)//判断整个数组里的数是否都大于当前磁道号 { printf(“n CSCAN调度结果: ”);for(i=0;i printf(“%d ”,array[i]);//将磁道号从小到大输出 } sum=array[m-1]-now;//计算移动距离 } else { while(array[k] 沈阳理工大学 沈阳理工大学课程设计专用纸 No14 { for(j=l;j>=0;j--){ printf(“%d ”,array[j]);} for(j=m-1;j>=r;j--){ printf(“%d ”,array[j]);} sum=2*(array[m-1]-array[0])-array[r]+now;//计算移动距离 }//磁道号减小方向 else { for(j=r;j // 操作界面 int main(){ int c;FILE *fp;//定义指针文件 int cidao[maxsize];//定义磁道号数组 int i=0,count;fp=fopen(“cidao.txt”,“r+”);//读取cidao.txt文件 if(fp==NULL)//判断文件是否存在 { printf(“n 请 先 设 置 磁 道!n”);exit(0);} while(!feof(fp))//如果磁道文件存在 沈阳理工大学 沈阳理工大学课程设计专用纸 No15 { fscanf(fp,“%d”,&cidao[i]);//调入磁道号 i++;} count=i-1;printf(“n-------------------n”);printf(“ 10-11OS课程设计--磁盘调度算法系统n”);printf(“ 计算机科学与技术二班n”);printf(“ 姓名:宋思扬n”);printf(“ 学号:0803050203n”);printf(“ 电话:************n”);printf(“ 2010年12月29日n”);printf(“n-------------------n”);printf(“n 磁道读取结果:n”);for(i=0;i 1、先来先服务算法(FCFS)n”);printf(“ 2、最短寻道时间优先算法(SSTF)n”);printf(“ 3、扫描算法(SCAN)n”);printf(“ 4、循环扫描算法(CSCAN)n”);printf(“ 5.退出n”);printf(“n”);printf(“请选择:”);scanf(“%d”,&c);if(c>5)break;switch(c)//算法选择 { case 1: FCFS(cidao,count);//先来先服务算法 printf(“n”);break;case 2: SSTF(cidao,count);//最短寻道时间优先算法 printf(“n”);break;case 3: 沈阳理工大学 沈阳理工大学课程设计专用纸 No16 SCAN(cidao,count);//扫描算法 printf(“n”);break;case 4: CSCAN(cidao,count);//循环扫描算法 printf(“n”);break;case 5: exit(0);} } return 0;} 6 运行结果 图2—1 运行界面 沈阳理工大学 沈阳理工大学课程设计专用纸 No17 图2—2 运行FCFS的界面 图2—3 运行SSTF的界面 图2—4 运行SCAN的界面 沈阳理工大学 沈阳理工大学课程设计专用纸 No18 图2—5 运行SCAN的界面 图2—6 运行CSCAN的界面 图2—7 运行CSCAN的界面 沈阳理工大学 沈阳理工大学课程设计专用纸 No19 运行结果: 四种磁盘调度运行结果正确,与预期的相符。设计心得 此次操作系统的课程设计,从理论到实践,在两个星期的日子里,可以说是苦多于甜,但是可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。 本次实验首先要了解磁盘调度的工作原理及四种调度方法的工作原理。在课程设计前的准备工作时,先把这部分工作做完了。在设计总的程序框架的时候,要注意各功能模块的位置,尽量做到简洁、有序;各功能模块与主程序要正确衔接。 在设计的过程中遇到许多问题,我设计的是四种调度算法中的后两种。例如:在最初程序设计时主要有两种构思:1)选用数据结构是链表的。2)选用数组。我最初尝试了用链表,觉得方便易懂,但是在循环扫描处出现了些问题,后来又转变了设计思路,选用了数组,直接进行排序,然后再联系到各功能模块。 同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,自身知识的很多漏洞,看到了自己的实践经验还是比较缺乏,理论联系实际的能力还急需提高。比如说编语言掌握得不好,应用程序编写不太会……通过这次课程设计之后,一定把以前所学过的知识重新温故。在此,也感谢在课程设计过程中帮我解惑的老师和同学。参考文献 [1] 《操作系统》 人民邮电出版社 宗大华 宗涛 陈吉人 编著 [2] 《C语言程序设计》 清华大学出版社 马秀丽 刘志妩 李筠 编著 [3] 《操作系统实验指导书》 沈阳理工大学 唐巍 菀勋 编著 沈阳理工大学 课程设计报告 题 目: 模拟请求页式管理 课程名称: 计算机操作系统 学 院: 信息工程学院 专 业: 计算机科学与技术 班 级: 14计本(1)学生姓名: * * * 学 号: 201403031** 指导教师: * * 成 绩: 开课时间: 2016-2017 学年 一 学期 模拟请求页式管理 第1章 需求分析 1.1设计要求 请求页式管理是一种常用的虚拟存储管理技术。本设计通过请求页式存储管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式管理的页面置换算法。本实验要求用Vc++或其他高级语言编写和调试。 编写程序实现: (1)先进先出页面置换算法(FIFO)(2)最近最久未使用页面置换算法(LRU)最佳置换页面置换算法(OPT)设计一个虚拟存储区和内存工作区,编程序演示以上三种算法的具体实现过程,并计算访问命中率。 1.2解决方案 首先确定实现语言使用c#实现图形化界面,后确定要实现哪些功能,比如算法选择,页面添加,模拟控制。然后确定输出结构以便于程序的测试和验证。将基本框架建立后再进行编程。编程前进行算法结构分析最后编程实现。 1.3算法实现原理 1、先进先出置换算法(FIFO): 发生缺页中断时按照页面进入内存顺序总是淘汰最先进入内存的页面。 2、最近最久未使用置换算法(LRU): 发生缺页中断时总是淘汰存在内存中最长时间未被使用的页面。 3、最佳置换算法(OPT): 发生缺页中断时若一个或几个页面将来将不会被调用则按先进先出原则淘汰页面,若将来都有调用则比较调用时刻选择最远时刻页面淘汰。 4、缺页率:缺页次数占页面调用次数的百分比。 第2章 概要设计 2.1数据设计 常变量:调用页面最大数量(MaxN),内存最大页面数(MaxM)待调用页面数组:page_dd[MaxN]存放等待调用的页面号 页面数组专用指针 page_p,用于指向page_dd数组中正需调入内存的页号 内存块数组:Memery[MaxM],存放内存当前存放的页号 缺页计数器:count,记录缺页次数 内存块状态数组:M1[MaxN],M2[MaxN],M3[MaxN],记录每次页面调用结束后内存各块的状态 缺页记录数组s[MaxN],用于记录页面调用时是否产生缺页中断,初始化为是 2.2函数设计 1、页面添加函数:void btnAdd_Click(object sender, EventArgs e)用于实现通过点击按钮实现数据输入。 2、内存初始化函数:init(int[] a, int[] b,int []m1,int[]m2,int[]m3)参数有页面数组、内存数组、状态数组,采用先进先出算法对内存先进行装满 服务于先进先出页面置换函数和最佳置换函数。 3、输出函数:void display(int[]a,int[]m1,int[]m2,int[]m3,char[]c)用于输出模拟结果,参数有页面数组,内存数组,状态数组,缺页记录数组。再模拟之后调用。 4、模拟控制函数:void btnmo_Click(object sender, EventArgs e)用于实现通过单击模拟按钮,根据用户所选算法进行模拟并显示结果。 5、先进先出算法模拟函数: void FIFO(int[] a, int[] b,int[]m1,int[]m2,int[]m3,char[] s)用于实现先进先出算法模拟,参数有页面数组,内存数组、内存状态记录数组,缺页记录数组。在模拟函数中调用。 6、最近最久未使用算法模拟函数: void LRU(int[] a, int[] b, int[] m1, int[] m2, int[] m3, char[] s)用于 3 实现最近最久未使用算法模拟,参数有页面数组,内存数组,内存状态记录数组,缺页记录数组。在模拟函数中被调用。 7、最近最久未使用函数辅助函数:void LUR_I(int[] a,int e)用于对最近最久未使用算法中所用辅助数组(记录页面存在时长)进行调整,参数有辅助数组及需调整的数据下标。在最近最久未使用函数中调用。 8、最佳置换算法模拟函数: void OPT(int[] a, int[] b, int[] m1, int[] m2, int[] m3, char[] s)用于模拟最佳置换算法。参数有页面数组,内存数组,内存状态记录数组,缺页记录数组。在模拟函数中被调用。 9、最佳置换算法辅助函数:void OPT_F(int[] a, int e)用于对最佳置换算法中的辅助数组进行调整。参数有辅助数组,需调整数据下标。在最佳置换算法中被调用。 10、重置函数:void btncz_Click(object sender, EventArgs e)用于重新选择算法进行新的模拟。 2.3主要算法设计 1、初始化函数算法: 第一步:将第一个页面调入内存,调整最佳置换算法辅助数组,缺页计数器加一,保存内存数组状态。 第二步:调用下一个页面并判断内存中是否有本页面有转第三步,无转第四步。第三步:更改缺页数组对应下标值,记录当前内存状态,调整最佳置换算法辅助数组,页面指针指向下一页。 第四步:将页面调入内存,调整最佳置换算法辅助函数,缺页计数器加一,保存内存数组状态。若内存尚不满转第一步。具体见图1初始化算法流程图。 开始页面调入内存缺页计数器加一记录内存状态调用下一页否否内存是否有该页面是记录内存状态修改缺页数组内存已满是结束 图1 初始化算法流程图 2、先进先出页面置换算法: 第一步:检查内存中是否已有需调用页面,有则转第二步,无则转第三步。第二步:记录当前内存状态,修改缺页数组对应下标值。 第三步:内存中无需要调用的页面,进行出队操作,然后进行入队操作,记录内存块状态,缺页计数器加一。 第四步:若页面数组未被调用结束转第一步。具体见图2先进先出算法流程图。 开始页面调入内存该页在内存中是否已存在是否否先出队操作后入队操作记录内存状态修改缺页数组值记录内存状态缺页计数器加一页面调用结束是结束 图2 先进先出算法流程图 3、最近最久未使用置换算法: 第一步:将页面调入内存,记录内存状态,缺页计数器加一,调整辅助数组,页面指针加一。 第二步:检查内存中是否已有所需页面,有转第三步,无转第一步。 第三步:修改缺页数组对应下标记录,记录内存状态,调整辅助数组,页面指针加一。第四步:内存是否已满,无则转第一步,是则转第五步。 第五步:检查内存中是否有所需页面,有则记录当前内存状态,修改缺页数组对应下标值。无则转第六步。 第六步:检查辅助数组找出最大值并记录其下标,置换内存中对应下标的数据,调整辅助数组,缺页计数器加一。 第七步:页面是否调用结束未结束则转第五步。具体见图3最近最久未使用算法流程图。 开始调入页面至内存记录内存状态计数器加一否调整辅助数组调用下一页内存中是否已有该页否内存已满是通过辅助数组确定淘汰页面是修改缺页数组记录内存状态调整辅助数组否页面置换记录内存状态计数器加一调用结束是结束 图3 最近最久未使用算法 4、最佳置换算法: 第一步:检查内存中是否已有所需页面,有则记录内存状态,修改缺页数组对应下标数值。无则转第二步。 第二步:判断内存中各页面的未来调用情况,记录是否还有调用,若有则记录调用时刻。 第三步:分析调用情况,内存中页面都在将来不会被调用转第四步,有一个被调用转第五步,有两个被调用转第六步,全被调用转第七步。 第四步:查找辅助数组找到内存中存在时间最长的页面进行置换,修改内存状态,缺页计数器加一,修改辅助数组。 第五步:查找到不会被调用的页面,并根据辅助数组选择最早进入内存的页面将其置换。修改内存状态,缺页计数器加一,修改辅助数组。 第六步:查找辅助数组找到将来不需要在调用的页面将其置换,修改辅助数组,记录内存状态,缺页计数器加一。 第七步:查找辅助数组,找寻最晚被调用的页面,将其置换。记录内存状态,修改辅助数组,缺页计数器加一。 第八步:页面是否调用完成,否则转第一步。具体见图4最佳置换算法流程图 开始调入页面记录内存状态计数器加一更新辅助函数是页面已存在否向后检查内存当前页面调用情况所有页面都不会再度调用否是一个页面会调用否否是两个页面会调用是否查找辅助数组得到最先进入页面通过辅助数组得到不会再调用的页面通过辅助数组获取最晚调用的页面通过辅助数组得到另外两个页面中最先进入的页面置换页面记录内存状态计数器加一更新辅助函数页面调用结束是结束 图4 最佳置换算法流程图 2.4界面设计 采用c# 设计windows窗体应用程序,使用下拉列表框选择算法,通过按钮添加待调用的页面。通过文本控件显示模拟结果。显示样式:第一行:算法名称; 第二行:调用页面顺序; 第三行至第五行显示内存在每调用一次页面后的状态; 第六行:是否缺页; 最后一行显示缺页率; 第3章 详细设计与实现 3.1函数设计 1、添加按钮功能实现代码 主要功能:实现单击一次添加一个调用页面,并给出相应的提示,如正在输入的是第几次调度页面,在输入为空时能够弹出对话框提示用户,在输入完成时为避免数组越界应在输入完成时隐藏;输入过程中始终保证时输入焦点。private void btnAdd_Click(object sender, EventArgs e){ if(txtAdd.Text!= “")//输入不为空才能继续输入 { page_dd[i_add] = Convert.ToInt32(txtAdd.Text);/*将输入值赋值给页面数组*/ txtShow.Text += txtAdd.Text + ” “;/*显示供用户查阅*/ i_add++;txtAdd.Clear();/*清空*/ if(i_add == MaxN)//输入结束时 { txtAdd.ReadOnly = true;//不允许继续输入 btnAdd.Hide();//按钮隐藏 return;} txtAdd.Focus();//设置为输入焦点 label2.Text = ”第“ +(i_add + 1)+ ”次调度页面:“;/*提示用户正在输入的是第几次调度页面*/ } /*输入为空则弹出对话框提示用户输入为空*/ else { MessageBox.Show(”请输入调用页面!“, ”输入为空“, MessageBoxButtons.OK, MessageBoxIcon.Warning);txtAdd.Focus();} } 2、初始化函数 主要功能:将内存一先进先出方式填满,并记录每个页面进入时间,服务于先进先出页面置换算法和最佳置换算法。 void init(int[] a, int[] b,int []m1,int[]m2,int[]m3){ /*内存未满时循环*/ for(int i = 0;i < MaxM&&page_p //调整辅助数组将刚进入内存的页面的对应时间 OPT_F(O_Q ,i); count++;//缺页计数器加一 m1[page_p] = b[0];//保存内存状态 m2[page_p] = b[1];m3[page_p] = b[2];page_p++;//调用下一页面 //检查内存中是否原先就有需要的页面; for(int j = 0;j <= i&&page_p s[page_p] = 'F';//缺页数组对应数据更改 m1[page_p] = b[0];//记录内存状态 m2[page_p] = b[1];m3[page_p] = b[2];OPT_F(O_Q,-1);//调整最佳置换算法辅助函数 page_p++;//调用下一页 j =-1;//重新开始寻找 } } } } 3、先进先出页面置换函数 主要功能:根据先进先出算法要求在产生缺页中断时采用先进先出方式确定淘汰页面,并在每次页面调用时记录下内存状态,缺页次数;采用循环队列使得每次出队的一定是最先进入内存的。 private void FIFO(int[] a, int[] b,int[]m1,int[]m2,int[]m3,char[] s){ int Fpage_p = page_p;int front, rear;//定义队列对手和对尾指针并初始化 front = 0;rear = MaxM1;int sa;for(;Fpage_p < MaxN;Fpage_p++){ sa = 0;for(int i = 0;i < MaxM;i++)//检查内存中是否已有要调用的页面。 { if(b[i] == a[Fpage_p]){ m1[Fpage_p] = b[0];m2[Fpage_p] = b[1];m3[Fpage_p] = b[2];s[Fpage_p] = 'F';sa = 1;break;} } if(sa == 0){ front =(front + 1)% MaxM; rear =(rear + 1)% MaxM;b[rear] = a[Fpage_p];m1[Fpage_p] = b[0];m2[Fpage_p] = b[1];m3[Fpage_p] = b[2];count++;} else continue;} } /*最近最久未使用算法辅助数组调整函数*/ private void LUR_I(int[] a,int e){ int temp;temp = a[e];a[e] = 1;for(int i = 0;i < MaxM;i++){ if(a[i] < temp && i!=e)a[i]++;} } /*最佳置换算法辅助数组调整函数*/ private void OPT_F(int[] a, int e){ if(e!=-1){ a[e] = 0;for(int i = 0;i < MaxM;i++){ if(i!= e)a[i]++;} } else for(int i = 0;i < MaxM;i++){ a[i]++;} } /*最近最久未使用算法*/ private void LRU(int[] a, int[] b, int[] m1, int[] m2, int[] m3, char[] s){ int[] L_Q = new int[MaxM]{3,3,3};int sa;for(int i = 0;i < MaxM && page_p < MaxN;i++){ b[i] = a[page_p];//调入内存 count++;m1[page_p] = b[0];//保存内存状态 m2[page_p] = b[1];m3[page_p] = b[2];LUR_I(L_Q, i);page_p++;for(int j = 0;j <= i && page_p < MaxN;j++){ if(b[j] == a[page_p]){ s[page_p] = 'F';m1[page_p] = b[0];m2[page_p] = b[1];m3[page_p] = b[2];LUR_I(L_Q, j);page_p++;j =-1;} } } for(;page_p < MaxN;page_p++){ sa = 0;for(int i = 0;i < MaxM;i++)//用的页面。{ if(b[i] == a[page_p]){ m1[page_p] = b[0];m2[page_p] = b[1];m3[page_p] = b[2];s[page_p] = 'F';LUR_I(L_Q, i);sa = 1;break;} } if(sa == 0){ 检查内存中是否已有要调40 for(int i = 0;i < MaxM;i++){ if(L_Q[i] == 3){ b[i] = a[page_p];m1[page_p] = b[0];m2[page_p] = b[1];m3[page_p] = b[2];LUR_I(L_Q, i);break;} } count++;} else continue;} } /*最佳置换算法*/ private void OPT(int[] a, int[] b, int[] m1, int[] m2, int[] m3, char[] s){ int sa;int O_p;int Ocount;int[] OPT_I=new int [MaxM ]{-1 ,-1 ,-1 };int[] OPT_J=new int [MaxM]{MaxN ,MaxN ,MaxN };for(;page_p < MaxN;page_p++){ for(int i = 0;i < MaxM;i++){ OPT_I[i] =-1;//刷新状态数组 OPT_J[i] = MaxN;} sa = 0;for(int i = 0;i < MaxM;i++)//检查内存中是否已有要调用的页面。 { if(b[i] == a[page_p]){ m1[page_p] = b[0];m2[page_p] = b[1];m3[page_p] = b[2];OPT_F(O_Q,-1); s[page_p] = 'F';sa = 1;break;} } if(sa == 0)//缺页 { Ocount = 0;for(int i = 0;i < MaxM;i++){ O_p = page_p + 1;for(;O_p < MaxN;O_p++){ if(b[i] == a[O_p]){ Ocount++;OPT_I[i] = 1;OPT_J[i] = O_p;break;} } } switch(Ocount){ case 0://全部页面以后都不会再度调用 int temp = 0;for(int i = 0;i < MaxM;i++){ if(O_Q[i] > O_Q[temp])temp = i;} b[temp] = a[page_p];m1[page_p] = b[0];m2[page_p] = b[1];m3[page_p] = b[2];OPT_F(O_Q ,temp);count++;break;case 1://有一个页面将在以后调用 temp = 0;for(int i = 0;i < MaxM;i++){ if(OPT_I[i]!= 1 && O_Q[i] > O_Q[temp])temp = i; } b[temp] = a[page_p];m1[page_p] = b[0];m2[page_p] = b[1];m3[page_p] = b[2];OPT_F(O_Q ,temp);count++;break;case 2: for(int i = 0;i < MaxM;i++){ if(OPT_I[i] ==-1){ b[i] = a[page_p];m1[page_p] = b[0];m2[page_p] = b[1];m3[page_p] = b[2];OPT_F(O_Q, i);count++;} } break;case 3: int p = 0;for(int i = 0;i < MaxM;i++){ if(OPT_J[i] >OPT_J[p])p = i;} b[p] = a[page_p];m1[page_p] = b[0];m2[page_p] = b[1];m3[page_p] = b[2];OPT_F(O_Q, p);count++;break;} } } } /*重置函数*/ private void btncz_Click(object sender, EventArgs e){ comboBox1.SelectedIndex = 0; txtAdd.Text = ”“;page_p = 0;i_add = 0;count = 0;//txtShow.Text = ”";for(int i = 0;i < MaxM;i++)Memery[i] =-1;for(int i = 0;i < MaxN;i++)s[i] = 'T';} } }第四篇:操作系统课程设计,磁盘调度算法范文
第五篇:操作系统课程设计报告