第一篇:计算机操作系统 课程设计报告(推荐)
操作系统课程设计报告
时间:2010-12-20~2010-12-31 地点:信息技术实验中心
计算机科学与技术专业 2008级2班15号
杨 烨
2010-12-31
信息工程学院计算机科学与技术082班
目录
一、课程设计的目的和意义...........................................................................................................2
二、进程调度算法模拟...................................................................................................................2
1、设计目的.............................................................................................................................2
2、设计要求.............................................................................................................................2
3、时间片轮转算法模拟.........................................................................................................3
实现思想:.......................................................................................................................3(1)流程图.....................................................................................................................3(2)程序代码.................................................................................................................3(3)运行结果.................................................................................................................5
4、先来先服务算法模拟.........................................................................................................6 算法思想...................................................................................................................................6
(1)流程图.....................................................................................................................7(2)程序代码.................................................................................................................7(3)运行结果...............................................................................................................11
三、主存空间的回收与分配.........................................................................................................11
1、设计目的...........................................................................................................................11
2、设计要求...........................................................................................................................12
3、模拟算法的实现...............................................................................................................13(1)流程图...................................................................................................................13(2)程序代码...............................................................................................................13(3)运行结果...............................................................................................................28
四、模拟DOS文件的建立和使用...............................................................................................28 设计目的.............................................................................................................................28 2 设计要求.............................................................................................................................28
3、模拟算法实现...................................................................................................................31(1)流程图...................................................................................................................31(2)程序代码...............................................................................................................31(3)运行结果...............................................................................................................36
五、磁盘调度算法模拟.................................................................................................................36
1.设计目的..............................................................................................................................36 2.实验原理..............................................................................................................................37 3.设计要求...........................................................................................................................37
4、模拟算法的实现...............................................................................................................38(1)各算法流程图.......................................................................................................38(2)程序代码...............................................................................................................39(3)运行结果...............................................................................................................45
六、总结.........................................................................................................................................45
信息工程学院计算机科学与技术082班
一、课程设计的目的和意义
本次操作系统课程设计的主要任务是进行系统级的程序设计。本课程设计是操作系统原理课程的延伸。通过该课程设计,使学生更好地掌握操作系统各部分结构、实现机理和各种典型算法,加深对操作系统的设计和实现思路的理解,培养学生的系统设计和动手能力,学会分析和编写程序。课程设计的实施将使学生在以下几个方面有所收获:
(1)加深对操作系统原理的理解,提高综合运用所学知识的能力;
(2)培养学生自主查阅参考资料的习惯,增强独立思考和解决问题的能力;(3)通过课程设计,培养严谨的科学态度和协作精神。
二、进程调度算法模拟
1、设计目的
(1)要求学生设计并实现模拟进程调度的算法:时间片轮转及先来先服务。(2)理解进程控制块的结构。(3)理解进程运行的并发性。(4)掌握进程调度算法。
2、设计要求
在多道程序运行环境下,进程数目一般多于处理机数目,使得进程要通过竞争来使用处理机。这就要求系统能按某种算法,动态地把处理机分配给就绪队列中的一个进程,使之运行,分配处理机的任务是由进程调度程序完成的。一个进程被创建后,系统为了便于对进程进行管理,将系统中的所有进程按其状态,将其组织成不同的进程队列。于是系统中有运行进程队列、就绪队列和各种事件的进程等待队列。进程调度的功能就是从就绪队列中挑选一个进程到处理机上运行。进程调度的算法有多种,常用的有优先级调度算法、先来先服务算法、时间片轮转算法。
进程是程序在处理机上的执行过程。进程存在的标识是进程控制块(PCB),进程控制块结构如下:
typedef struct node { char name[10];/* 进程标识符 */ int prio;/* 进程优先数 */ int round;/* 进程时间轮转时间片 */ int cputime;/* 进程占用 CPU 时间*/ int needtime;/* 进程到完成还需要的时间*/ int count;/* 计数器*/ char state;/* 进程的状态*/ struct node *next /*链指针*/ }PCB;系统创建一个进程,就是由系统为某个程序设置一个PCB,用于对该进程进行控制和管
信息工程学院计算机科学与技术082班
理,进程任务完成,由系统收回其PCB,该进程便消亡。每个进程可以有三个状态:运行状态、就绪状态和完成状态。
用C语言、C++或者Java语言编写一个程序实现进程调度的算法,模拟进程调度的过程,加深对进程控制块概念和进程调度算法的理解。
本任务要求完成时间片轮转及先来先服务两个算法。
3、时间片轮转算法模拟
实现思想:
每次调度时,系统吧处理机分配给队列首进程让器执行一个时间片,当执行的时间片用完时,由一个计时器发出时钟中断请求,调度根据这个请求停止该进程的运行将其送到就绪队列的末尾,再把处理机分给就绪队列中新的队首进程,同时让它执行一个时间片。(1)流程图
进程调度—时间片轮转开始输入进程总数输入各进程信息更新在运行的进程的已运行时间输出为就绪状态的进程信息N输出此时为就绪状态的进程信息当前进程是否运行结束是否存在下个进程Y指向下一个进程YN结束跳过
(2)程序代码
#include
// PCB
struct PNode *next;// 定义指向下一个节点的指针
char name[10];
// 定义进程名,并分配空间
信息工程学院计算机科学与技术082班
int All_Time;
// 定义总运行时间
int Runed_Time;
// 定义已运行时间
char state;
// 定义进程状态 Ready / End } * Proc;// 指向该PCB的指针 int ProcNum;// 总进程个数
void InitPCB(Proc &H)// 初始化就绪队列
{
cout<<“请输入总进程个数: ”;
cin>>ProcNum;// 进程总个数
int Num=ProcNum;
H=(Proc)malloc(sizeof(PNode));// 建立头节点
H->next=NULL;
Proc p=H;//定义一个指针
cout<<“总进程个数为 ”<
while(Num--){
p=p->next=(Proc)malloc(sizeof(PNode));
cout<<“进程名 总运行时间 已运行时间 :”;
cin>>p->name>>p->All_Time>>p->Runed_Time;
p->state='R';
p->next=NULL;}
p->next=H->next;
} void DispInfo(Proc H)//输出运行中的进程信息 {
Proc p=H->next;
do {
if(p->state!= 'E')
//如果该进程的状态不是End的话
{
cout<<“进程名:”<
name<<“t总运行时间:”<
All_Time
<<“t已运行时间:”<
Runed_Time
<<“t状态:”<
state< p=p->next; } else p=p->next; } } void SJP_Simulator(Proc &H)// 时间片轮转法 { while(p!= H->next);// 整个进程链条始终完整,只是状态位有差异 信息工程学院计算机科学与技术082班 cout< int flag=ProcNum;// 记录剩余进程数 int round=0;// 记录轮转数 Proc p=H->next; while(p->All_Time > p->Runed_Time) { // 即未结束的进程 round++; cout< p->Runed_Time++; // 更改正在运行的进程的已运行时间 DispInfo(H); // 输出此时为就绪状态的进程的信息 if(p->All_Time == p->Runed_Time){ // 并判断该进程是否结束 p->state='E'; flag--; cout< name<<“ 进程已运行结束,进程被删除!n”; } p=p->next; while(flag && p->All_Time == p->Runed_Time) p=p->next;// 跳过先前已结束的进程 } cout< Proc H; InitPCB(H);// 数据初始化 DispInfo(H);// 输出此刻的进程状态 SJP_Simulator(H);// 时间片轮转法 system(“pause”);}(3)运行结果 输入相关进程信息: 输出相关运行结果: 信息工程学院计算机科学与技术082班 4、先来先服务算法模拟 算法思想 按照进程的某种顺序进行排序,然后按照这个顺序进行调度。例如:可以按照作业提交时间或进程变为就绪状态的先后次序来分派处理器,让排在后面的进程占用处理器,知道该进程执行完或者由于某种原因被阻塞才让出处理器。 在该调度策略中还规定,当有一个事件发生(如一个I/O操作完成)时,会有一些进程被唤醒,这些被唤醒的进程并不能立即恢复执行,而是要等到当前运行的进程出让处理器后才可以被调度执行。采用此算法存在以下几个特点: 周转时间:对进程i来说,假设Tei是进程的完成时间,Tsi是进程的提交时间,那么进程i的周转时间Ti=进程完成时间-进程提交时间; 进程平均周转时间:T=1/nETi; 进程带权周转时间=进程等待时间+进程运行时间。 信息工程学院计算机科学与技术082班 (1)流程图 Begin输入当前磁道号now磁头移动距离sum=abs(now-array[0])磁头移动总距离sum+=abs(array[j]-array[i])输出磁盘调度序列array[j]目前位置编程当前的位置i++j (2)程序代码 #include “stdio.h” #include #define getpch(type)(type*)malloc(sizeof(type))#define NULL 0 struct pcb { /* 定义进程控制块PCB */ char name[10];char state;int super; 信息工程学院计算机科学与技术082班 int ntime;int rtime;struct pcb* link;}*ready=NULL,*p;typedef struct pcb PCB; void sort()/* 建立对进程进行优先级排列函数*/ { PCB *first, *second;int insert=0; if((ready==NULL)||((p->super)>(ready->super)))/*优先级最大者,插入队首*/ { p->link=ready;ready=p;} else /* 进程比较优先级,插入适当的位置中*/ { first=ready;second=first->link;while(second!=NULL){ if((p->super)>(second->super))/*若插入进程比当前进程优先数大,*/ { /*插入到当前进程前面*/ p->link=second;first->link=p;second=NULL;insert=1;} else /* 插入进程优先数最低,则插入到队尾*/ { first=first->link;second=second->link;} } if(insert==0)first->link=p;} } void input()/* 建立进程控制块函数*/ { int i,num; printf(“n 请输入进程数:”);scanf(“%d”,&num);for(i=0;i 信息工程学院计算机科学与技术082班 printf(“n 进程号No.%d:n”,i+1);p=getpch(PCB);printf(“n 输入进程名:”);scanf(“%s”,p->name);printf(“n 输入进程优先数:”);scanf(“%d”,&p->super);printf(“n 输入进程运行时间:”);scanf(“%d”,&p->ntime);printf(“n”); p->rtime=0;p->state='w';p->link=NULL; sort();/* 调用sort函数*/ } } int space(){ int l=0;PCB* pr=ready;while(pr!=NULL){ l++;pr=pr->link;} return(l);} void disp(PCB * pr)/*建立进程显示函数,用于显示当前进程*/ { printf(“n qname t state t super t ndtime t runtime n”);printf(“|%st”,pr->name);printf(“|%ct”,pr->state);printf(“|%dt”,pr->super);printf(“|%dt”,pr->ntime);printf(“|%dt”,pr->rtime);printf(“n”);} void check()/* 建立进程查看函数 */ { PCB* pr; printf(“n **** 当前正在运行的进程是:%s”,p->name);/*显示当前运行进程*/ disp(p);pr=ready; printf(“n ****当前就绪队列状态为:n”);/*显示就绪队列状态*/ while(pr!=NULL){ 信息工程学院计算机科学与技术082班 disp(pr);pr=pr->link;} } void destroy()/*建立进程撤消函数(进程运行结束,撤消进程)*/ { printf(“n 进程 [%s] 已完成.n”,p->name);free(p);} void running()/* 建立进程就绪函数(进程运行时间到,置就绪状态*/ { (p->rtime)++; if(p->rtime==p->ntime) destroy();/* 调用destroy函数*/ else { (p->super)--;p->state='w'; sort();/*调用sort函数*/ } } int main()/*主函数*/ { int len,h=0;char ch;input();len=space(); while((len!=0)&&(ready!=NULL)){ ch=getchar();h++; printf(“n The execute number:%d n”,h);p=ready;ready=p->link;p->link=NULL;p->state='R';check();running(); printf(“n 按任一键继续......”);ch=getchar();} printf(“nn 进程已经完成.n”); 信息工程学院计算机科学与技术082班 ch=getchar();}(3)运行结果 输入相关进程信息: 输出相关运行结果: 三、主存空间的回收与分配 1、设计目的 主存是中央处理器能直接存取指令和数据的存储器,能否合理地利用主存,在很大程度 信息工程学院计算机科学与技术082班 上将影响到整个计算机系统的性能。主存分配是指在多道作业和多进程环境下,如何共享主存空间。主存回收是指当作业执行完毕或进程运行结束后将主存空间归还给系统。主存分配与回收的实现是与主存储器的管理方式有关。本次设计主要是为了帮助学生深入理解主存空间的分配与回收的几种算法。 (1)掌握最先适应分配算法(2)掌握最优适应分配算法(3)掌握最坏适应分配算法 2、设计要求 用户提出内存空间请求,系统根据申请者要求,按照最先适应分配算法的分配策略分析内存空间的使用情况,找出能满足请求的空闲区,分给申请者,当程序执行完毕时,系统要收回它所占用的内存空间。建立空闲数据文件,空闲区数据文件包括若干行,每行有两个字段:起始地址、内存块大小(均为整数),各字段以逗号隔开。下面是一个空闲区数据文件的示例: 0,10 10,08 18,10 28,06 34,10 44,09 读取空闲区数据文件,建立空闲区表并在屏幕上显示空闲内存状态,空闲区表记录了可供分配的空闲内存的起始地址和大小,用标志位指出该分区是否是未分配的空闲区。 接收用户的内存申请,格式为:作业名、申请空间的大小。 按照内存分配算法中的一种方法选择一个空闲区,分割并分配,修改空闲区表,填写内存已分配区表(起始地址、长度、标志位),其中标志位的一个作用是指出该区域分配给哪个作业。 进程结束后回收内存。空闲区表的结构如下: typedef struct node{ int start;int length;char tag[20];}job;本次设计要求完成如下算法: (1)设计一个内存分配回收的程序使用最先适应分配算法(2)设计一个内存分配回收的程序使用最优适应分配算法(3)设计一个内存分配回收的程序使用最坏适应分配算法 用户提出内存空间请求,系统根据申请者要求,选择上述算法的一种分配策略分析内存空间的使用情况,找出合适的空闲区,分给申请者,当进程执行完毕时,系统收回它所占用的内存空间。 信息工程学院计算机科学与技术082班 3、模拟算法的实现 (1)流程图 内存分配开始划定内存总量输入进程信息所需内存<剩余内存?Y在剩余空间中划分出所需空间N剩余空间分配给请求者,修改有关数据输出进程信息结束 (2)程序代码 #include };//分区指针的链表 //当把空闲分区链表和占用分区链表按照地址先后顺序合并 //以显示整个内存情况的时候使用 struct AreaPointer_list{ struct area * data;struct AreaPointer_list * next;int start;//分区的其始地址 int length;//分区的长度 int job;//若被作业占用值为作业号,若空闲值为0 struct area * next; 信息工程学院计算机科学与技术082班 };struct area * idle;struct area * used; //全局变量,空闲分区链表头指针 //全局变量,占用分区链表头指针 struct AreaPointer_list * whole = NULL;//全局变量,分区指针链表头指针 //p(previcious)n(next)指出在链表中的何处插入新生成的元素 //p==NULL 在链表头插入,返回头指针 //p!=NULL 在链表中或链表尾插入,返回当前插入的元素的指针 struct area * insert(int s,int l,int j,struct area * p,struct area * n){ } //此模块居于次要地位,只被使用一次 //打印分区链表 void print(struct area * head){ if(head == NULL){ } else{ while(head!= NULL){ if(head->job == 0)else printf(“begin:%dKtlength:%dKtuse:Job%dt|n”,head->start,head->length,hea printf(“begin:%dKtlength:%dKt空闲tt|n”,head->start,head->length);printf(“Area list is null...n”);struct area * current =(struct area *)malloc(LEN);current->start = s;current->length = l;current->job = j;if(p == NULL){//在链表头插入 } else{ } if(p->next == NULL){//在链表尾插入 } else{//在链表中插入 } return current;current->next = p->next;p->next = current;current->next = NULL;p->next = current;current->next = n;return current; d->job); 信息工程学院计算机科学与技术082班 } void file_print(struct area * head,FILE * file){ if(head == NULL){ } else{ while(head!= NULL){ if(head->job == 0)else fprintf(file,“begin:%dKtlength:%dKtuse:Job%dt|n”,head->start,head->length,fprintf(file,“begin:%dKtlength:%dKt空闲tt|n”,head->start,head->length);fprintf(file,“Area list is null...n”); } } head = head->next; head->job); } //打印分区链表 } } head = head->next;//释放分区链表空间 void free_AreaList(struct area * head){ } //释放分区链表空间 //在分区链表中搜索插入位置 //flag==0 表明分区链表按起始地址从小到大排列 //flag==1 表明分区链表按分区长度从小到大排列 //输入参数 element 不能为NULL struct area * search_pos(struct area * element,struct area * head,int flag){ struct area * p = NULL;while(head!= NULL){ if(flag == 0){ if(element->start < head->start)struct area * temp;while(head!= NULL){ } temp = head;head = head->next;free(temp); 信息工程学院计算机科学与技术082班 } //返回值p==NULL表明插入位置在链表头 //返回值p!=NULL表明插入位置在p 之后 //进行分区链表的实际插入工作 //flag==0 表明分区链表按起始地址从小到大排列 //flag==1 表明分区链表按分区长度从小到大排列 //输入参数 element->next 要为NULL struct area * insert_list(struct area * element,struct area * list,int flag){ if(list == NULL)else{ } return list;struct area * pos = search_pos(element,list,flag);if(pos == NULL){ } else{ } element->next = pos->next;pos->next = element;element->next = list;list = element;list = element; } return p;} else { } p = head;head = head->next;if(element->length < head->length) break; break;}//返回插入元素之后新链表的头指针 //进行查询空闲分区链表动态分配分区的实际工作,算法步骤: //1。查询空闲分区链表中是否有长度大于或等于申请长度的分区,若没有返回FALSE //2。若查找到符合条件的分区,把它从空闲链表中取出 //3。根据请求把取出的空闲分区分块,把新的占用分区和剩余空闲分区分别插入链表 //注意:插入占用分区链表按照固定的地址先后顺序,插入空闲分区链表的方式要根据flag的值 int memory_alloc(int length,int job,int flag){ struct area * used_element; 信息工程学院计算机科学与技术082班 struct area * free_element;struct area * head = idle;struct area * head_temp = used;struct area * p = NULL;//检测输入的作业号是否存在 while(head_temp!= NULL){ } //在空闲分区链表中查找 while(head!= NULL){ } if(head!= NULL){ } else return 0;//生成新的占用区链表元素并插入占用区链表 used_element =(struct area *)malloc(LEN);used_element->start = head->start;used_element->length = length;used_element->job = job;used_element->next = NULL;used = insert_list(used_element,used,0);//若空闲分区分块后有剩余,生成新的空闲区链表元素并插入空闲区链表 if(head->length > length){ free_element =(struct area *)malloc(LEN);//从空闲区链表中取出 if(p == NULL)//链表中的第一个分区符合条件 { } else { } head->next = NULL;p->next = head->next;idle = idle->next;if(head->length >= length)break;p = head;head = head->next;if(head_temp->job == job)return 2;head_temp = head_temp->next; 信息工程学院计算机科学与技术082班 } //进行查询占用分区链表动态释放分区的实际工作,算法步骤: //1。根据作业号查询到占用分区链表中要释放的分区,若没有返回FALSE //2。若查找到要释放的分区,把它从空闲链表中取出 //3。根据取出的分区的数据建立新的空闲分区 //4。在空闲分区链表中查询是否有和新空闲分区相邻的空闲分区,有则合并 //5。根据flag的取值按照特定方式插入空闲分区链表 int memory_free(int job,int flag){ struct area * used_element;struct area * free_element;struct area * head = used;struct area * p = NULL;struct area * previcious1 = NULL;struct area * current1 = NULL;struct area * previcious2 = NULL;struct area * current2 = NULL;//根据作业号在占用分区链表中查找 while(head!= NULL){ } if(head!= NULL){ //从占用区链表中取出 if(p == NULL)//链表中的第一个分区符合条件 { } else { used = used->next;if(head->job == job)break;p = head;head = head->next; } //释放空间 free(head);return 1;free_element->start = head->start + length;free_element->length = head->length-length;free_element->job = 0;free_element->next = NULL;idle = insert_list(free_element,idle,flag); 信息工程学院计算机科学与技术082班 } else return 0;//建立新的空闲分区 used_element = head;free_element =(struct area *)malloc(LEN);free_element->start = used_element->start;free_element->length = used_element->length;free_element->job = 0;free_element->next = NULL;//从空闲区链表查找和新的空闲分区相邻分区 head = idle;p = NULL;while(head!= NULL){ } //合并相邻空闲分区 if(current1!= NULL){ } //把和新分区相邻的分区从空闲分区链表中取出 if(previcious1 == NULL)else previcious1->next = current1->next;current1->next = NULL;//修改新空闲分区的相关数据 free_element->start = current1->start;free_element->length = free_element->length + current1->length;idle = idle->next;if(head->start + head->length == used_element->start){ } if(used_element->start + used_element->length == head->start){ } p = head;head = head->next;previcious2 = p;current2 = head;previcious1 = p;current1 = head;} head->next = NULL;p->next = head->next; 信息工程学院计算机科学与技术082班 } //和分区指针链表相关的操作,用来合并空闲分区链表和占用分区链表,保存链表元素的指针 struct AreaPointer_list * search_position(int s,struct AreaPointer_list * head){ } struct AreaPointer_list * emerge(struct area * idle_temp,struct area * used_temp){ struct AreaPointer_list * previcious;struct AreaPointer_list * temp; if(used_temp!= NULL){ whole =(struct AreaPointer_list *)malloc(LEN_POINTER_LIST);whole->data = used_temp;whole->next = NULL;previcious = whole;used_temp = used_temp->next;while(used_temp!= NULL){ temp =(struct AreaPointer_list *)malloc(LEN_POINTER_LIST);struct AreaPointer_list * p = NULL;while(head!= NULL){ } return p;if(s <(head->data)->start)break;p = head;head = head->next;if(current2!= NULL){ } //根据flag的取值按照特定方式插入空闲分区链表 idle = insert_list(free_element,idle,flag);//释放空间 free(used_element);return 1;//把和新分区相邻的分区从空闲分区链表中取出 if(previcious2 == NULL)else previcious2->next = current2->next;current2->next = NULL;//修改新空闲分区的相关数据 free_element->length = free_element->length + current2->length;idle = idle->next; 信息工程学院计算机科学与技术082班 } void printall(struct AreaPointer_list * head){ struct area * data_temp;if(head == NULL)else{ while(head!= NULL){ data_temp = head->data;if(data_temp->job == 0)else printf(“begin:%dKtlength:%dKt空闲tt|n”,data_temp->start,data_temp->lenprintf(“Area pointer list is null...n”); } while(idle_temp!= NULL){ } return whole;struct area * idle_next = idle_temp->next;struct AreaPointer_list * pos = search_position(idle_temp->start,whole);if(pos == NULL){ } else { } idle_temp = idle_next;temp =(struct AreaPointer_list *)malloc(LEN_POINTER_LIST);temp->data = idle_temp;temp->next = pos->next;pos->next = temp;temp =(struct AreaPointer_list *)malloc(LEN_POINTER_LIST);temp->data = idle_temp;temp->next = whole;whole = temp; } temp->data = used_temp;temp->next = NULL;previcious->next = temp;previcious = temp;used_temp = used_temp->next; gth); printf(“begin:%dKtlength:%dKtuse:Job%dt|n”,data_temp->start,data_temp->length,data_temp->job);head = head->next; 信息工程学院计算机科学与技术082班 } void file_printall(struct AreaPointer_list * head,FILE * file){ struct area * data_temp;if(head == NULL)else{ while(head!= NULL){ data_temp = head->data;if(data_temp->job == 0)else fprintf(file,“begin:%dKtlength:%dKt空闲tt|n”,data_temp->start,data_tempfprintf(file,“Area pointer list is null...n”);} } ->length); fprintf(file,“begin:%dKtlength:%dKtuse:Job%dt|n”,data_temp->start,data_temp->length,data_temp->job); } void free_PointerList(struct AreaPointer_list * head){ } //和分区指针链表相关的操作,用来合并空闲分区链表和占用分区链表,保存链表元素的指针 void input_by_hand(){ int job;int is_alloc;//1 申请分区 0 释放分区 int length;int flag;printf(“请选择分区分配算法:输入0---最先适配 输入1---最优适配n”);scanf(“%d”,&flag);while(flag!= 0 && flag!= 1){ printf(“数据输入错误,请参照提示重新输入n”);scanf(“%d”,&flag);struct AreaPointer_list * temp;while(head!= NULL){ } temp = head;head = head->next;free(temp); } } head = head->next; 信息工程学院计算机科学与技术082班 } if(flag == 0)printf(“选择最先适配算法--->请输入请求队列数据:(输入 0 0 0 结束)n”);printf(“选择最优适配算法--->请输入请求队列数据:(输入 0 0 0 结束)n”);if(flag == 1)printf(“输入数据格式:作业号(int>0)[输入1--申请|输入0--释放] 分区长度(int>0)n”);printf(“例如输入 5 1 130 表示 作业5申请130Kn”);printf(“例如输入 3 0 200 表示 作业3释放200Kn”);while(1)//输入 0 0 0 结束 { scanf(“%d%d%d”,&job,&is_alloc,&length);if(job == 0 && is_alloc == 0 && length == 0){ } if(is_alloc == 1){ } if(is_alloc == 0){ int r = memory_free(job,flag);if(!r){ int r = memory_alloc(length,job,flag);if(!r){ } if(r == 2){ } printf(“n”); printf(“输入作业号已存在于占用分区链表,请重新输入...n”);printf(“n”);continue;printf(“n”); printf(“没有符合条件的空闲分区可供分配,请等待释放...n”);printf(“n”);continue;printf(“数据输入错误,请参照提示重新输入n”);scanf(“%d%d%d”,&job,&is_alloc,&length);if(job == 0 && is_alloc == 0 && length == 0) return;break;while(job<=0 ||(is_alloc!= 0 && is_alloc!= 1)|| length<=0) 信息工程学院计算机科学与技术082班 } /*void input_by_file(int flag){ int job;int is_alloc;//1 申请分区 0 释放分区 int length;char* result;int r;FILE * file1;FILE * file2;if(flag == 0)else result = “result_data_2.txt”;result = “result_data_1.txt”; } //释放空间 free_AreaList(idle);free_AreaList(used);idle = NULL;used = NULL; } emerge(idle,used);printf(“n”);printf(“------------------n”);printf(“空闲分区链表:ttttt|n”);print(idle);printf(“tttttt|n”);printf(“占用分区链表:ttttt|n”);print(used);printf(“tttttt|n”);printf(“整个内存情况:ttttt|n”);printf(“低地址tttttt|n”);printall(whole);printf(“高地址tttttt|n”);printf(“------------------n”);printf(“n”);free_PointerList(whole);whole = NULL; } printf(“n”); printf(“没有与指定作业号符合的占用分区,请重新输入...n”);printf(“n”);continue; 信息工程学院计算机科学与技术082班 if((file1 = fopen(“source_data.txt”,“r”))== NULL){ } if((file2 = fopen(result,“w”))== NULL){ } if(flag == 0){ } else { } while(!feof(file1)){ fscanf(file1,“%d%d%d”,&job,&is_alloc,&length);if(job<=0 ||(is_alloc!= 0 && is_alloc!= 1)|| length<=0){ } if(is_alloc == 1){ printf(“JOB %d申请%dKnn”,job,length);fprintf(file2,“JOB %d申请%dKnn”,job,length);r = memory_alloc(length,job,flag);if(!r){ } if(r == 2){ printf(“输入作业号已存在于占用分区链表,不于处理nn”); printf(“没有符合条件的空闲分区可供分配,不于处理nn”);fprintf(file2,“没有符合条件的空闲分区可供分配,不于处理nn”);continue;printf(“文件中数据%d %d %d输入的格式错误,不于处理nn”,job,is_alloc,lengtfprintf(file2,“文件中数据%d %d %d输入的格式错误,不于处理nn”,job,is_alloc,continue;printf(“按照最优分配算法得出的结果:nn”);fprintf(file2,“按照最优分配算法得出的结果:nn”);printf(“按照最先分配算法得出的结果:nn”);fprintf(file2,“按照最先分配算法得出的结果:nn”);printf(“不能打开source_data.txt文件...n”);exit(0);printf(“不能打开source_data.txt文件...n”);exit(0); h); length); 信息工程学院计算机科学与技术082班 } else { } emerge(idle,used);printf(“------------------n”);fprintf(file2,“------------------n”);printf(“空闲分区链表:ttttt|n”);fprintf(file2,“空闲分区链表:ttttt|n”);print(idle);file_print(idle,file2);printf(“tttttt|n”);fprintf(file2,“tttttt|n”);printf(“占用分区链表:ttttt|n”);fprintf(file2,“占用分区链表:ttttt|n”);print(used);file_print(used,file2);printf(“tttttt|n”);fprintf(file2,“tttttt|n”);printf(“整个内存情况:ttttt|n”);fprintf(file2,“整个内存情况:ttttt|n”);printf(“低地址tttttt|n”);fprintf(file2,“低地址tttttt|n”);printall(whole);file_printall(whole,file2);printf(“高地址tttttt|n”);fprintf(file2,“高地址tttttt|n”);printf(“------------------n”);fprintf(file2,“------------------n”);printf(“n”);fprintf(file2,“n”);printf(“JOB %d释放%dKnn”,job,length);fprintf(file2,“JOB %d释放%dKnn”,job,length);r = memory_free(job,flag);if(!r){ } printf(“没有与指定作业号符合的占用分区,不于处理nn”);fprintf(file2,“没有与指定作业号符合的占用分区,不于处理nn”);continue; } fprintf(file2,“输入作业号已存在于占用分区链表,不于处理nn”);continue; 信息工程学院计算机科学与技术082班 }*/ int main() } { idle = insert(0,640,0,NULL,NULL);used = NULL;input_by_hand(); } printf(“========================================nn”);fprintf(file2,“========================================nn”);//释放空间 free_AreaList(idle);free_AreaList(used);idle = NULL;used = NULL;fclose(file1);fclose(file2);free_PointerList(whole);whole = NULL; 信息工程学院计算机科学与技术082班 (3)运行结果 四、模拟DOS文件的建立和使用 设计目的 磁盘文件是磁盘上存储的重要信息,通过本实验模拟DOS文件的建立和使用情况,理解磁盘文件的物理结构。文件管理是操作系统中重要的内容之一,不同的文件系统提供了不同的物理结构,通过实验,深入理解文件的物理结构与存取方法之间的关系,以便更好的掌握文件系统的概念。设计要求 <1> 模拟设计DOS操作系统中磁盘文件的存储结构 DOS操作系统对磁盘文件的管理采用链接结构,将所有的链接指针集中在一起,存放在文件分配表(FAT)中。连接文件的第一个物理块号登记在文件目录中。其设计思想是:假定磁盘上共有N个物理块可供使用,当要存放文件时,从FAT表中寻找其值为0的项,用其对应的物理块存放文件信息,并把文件占有的各物理块用链接指针登记在FAT表中,再把文 信息工程学院计算机科学与技术082班 件的第一个物理块号登记在文件目录中。 文件目录及FAT表如图所示: 在DOS中FAT表的前两项用来记录磁盘的类型。而从第2项开始记录磁盘的分配情况和文件各物理块的链接情况。在FAT表中第三项的值如果为0,表示对应的第三块空闲。由图还知道文件A的各记录依次存放在第2、第4、第15、第16、第50等六个物理块中。第50块中的指针为FFF,表示文件A的结束。文件B的各记录依次存放在第7、第10、第20等三个物理块中。第20块中的指针为FFF。 假定磁盘存储空间共有100个物理块,设计一个文件分配表。为了简单,文件分配表可用一个数组定义,其中每一个元素与一个物理块对应。当第 i 个元素为 0 时,表示第 i 块空闲;当第 i 个元素既不为 0 也不为 FFF 时,其值表示该文件的下一个物理块号。另外,再设一个空闲块总数变量记录系统还有的空闲块数。为了简单,假定一个物理块指存放一个逻辑记录,要求设计一个程序,把文件的逻辑记录结构转换成 DOS 的链接结构。当用户要求将已在主存的文件保存在磁盘上时,给出文件名及文件的记录个数,系统应能在磁盘上正确地保存文件。或当用户要求给指定文件增加记录时,也应正确的实现,并插在指定记录之后。 为了正确地执行模拟程序,可用键盘模拟输入用户的要求。输入格式为: write(文件名,记录个数)或 insert(文件名,逻辑记录号)<2> 模拟设计便于直接存取的索引文件结构 为了便于用户直接存取文件的各个逻辑记录,在 MS-DOS 中通过文件目录,再沿着链查找FAT表,便可直接找到指定逻辑记录对应的物理块。在小型机或更高级的文件系统中,直接存取文件的方法是为每个文件建立一个索引表,指出各逻辑记录与物理块的对应关系。最简单的形式是一个逻辑记录对应一个物理块。文件目录与索引表的关系如图所示。 信息工程学院计算机科学与技术082班 通常索引表按照逻辑记录顺序建立,这样既有利于顺序存储,又有利于直接存储。为了标识哪些记录已经建立,哪些记录还没建立,故在索引表中增设一个标志位。写文件或插入一个记录的过程是寻找一个空闲物理块,然后将其填入索引表对应项中。其建立过程同第一题,即 write(文件名,记录号)和 insert(文件名,记录号)。 要求用位示图描绘出磁盘的使用情况,并要求模拟程序执行过程的每一步都能显示文件目录、位示图、索引表。 信息工程学院计算机科学与技术082班 3、模拟算法实现 (1)流程图 创建文件流程开始读取文件流程开始查询未打开的文件表查询已打开文件表在未打开表中?N是否在已打开的文件表里?YY是否在已打开表中查询剩余未打开的文件表NYY显示无文件是否在剩余表中?N输出无文件读取文件记录读取文件记录返回Read参数合法?Nwrite参数是否合法?Y返回写入磁盘显示参数非法显示成功Y显示参数非法根据参数读取记录并显示END (2)程序代码 #include }; char filename[10];int filestart;int filelength; 信息工程学院计算机科学与技术082班 FILEINFO file[10];int FAT[N],blankspace;//FAT表和剩余空间 void printfmenu(){ int i;cout< 文件名 起始块号 文件长度”< } void write(char *tmpname,int tmplength){ int last,i,j;//复制文件名和文件块个数 strcpy(file[fnum].filename,tmpname);file[fnum].filelength=tmplength;//存文件 for(i=2;i } for(i=1;i for(j=2;j FAT[last]=j; if(FAT[i]==0){ } file[fnum].filestart=i;//首个空闲块为文件开始块 last=i;FAT[last]=FFF;break;int i;cout<<“空闲块数:”< } cout<<“ No.”< 信息工程学院计算机科学与技术082班 } void insert(char *tmpname,int insertpoint){ int i;int last,brpoint;//寻找要执行插入操作的文件,将其数组下标存入last for(i=0;i } //brpoint记录当前文件扫描到的位置 brpoint=file[last].filestart; for(i=0;i } //改变空闲块个数与文件长度 if(FAT[i]==0){ } FAT[i]=FAT[brpoint];FAT[brpoint]=i;break;brpoint=FAT[brpoint];//扫描直到找到插入位置 if(strcmp(file[i].filename,tmpname)==0){ } else printf(“没有指定文件!n”);last=i;break; } FAT[last]=FFF;//文件末存结束标记 blankspace-=tmplength;//改变空闲块个数 fnum++;cout<<“name and size :”< } last=j;FAT[last]=FFF;break; 信息工程学院计算机科学与技术082班 } void itol(int i){ //LPCTSTR yy;char zz[10];file[last].filelength++;blankspace--;cout<<“name and size :”< //sprintf(zz, “%d”, i); //itoa(i,zz,10); //yy = LPCTSTR(zz); } void ctol(char *c){ } void Graph(){ int i,x=200,y=50;//initgraph(640, 480);//setfillstyle(SOLID_FILL,WHITE);//floodfill(5,5,WHITE);//setcolor(BLACK);for(i=0;i } //getch();//closegraph(); //moveto(x+(i/20)*60-25,y+(i%20)*20);itol(i);//rectangle(x+(i/20)*60,y+(i%20)*20,x+(i/20)*60+30,y+(i%20)*20+20);//moveto(x+(i/20)*60,y+(i%20)*20);if(FAT[i]==FFF)ctol(“FFF”);ctol(“FDF”);else if(FAT[i]==FDF)else itol(FAT[i]);//LPCTSTR yy;//yy = LPCTSTR(c);//moverel(3,2);//outtext(yy);//moveto(x+i*2,y+20);//moverel(5,3);//outtext(yy);//return yy; 信息工程学院计算机科学与技术082班 } void main(){ } int i;char tmpname[10];int tmplength;//要写入文件长度 int o;//命令 fnum=0;for(i=0;i } FAT[0]=FDF;FAT[1]=FFF;FAT[3]=999;blankspace=98;while(1){ } printFAT();cin.get();cout<<“请选择: 1.写入 2.插入 3.显示文件目录 4.显示FAT表”< } case 1: cout<<“输入文件名:”; cin>>tmpname; cout<<“输入文件长度:”;cin>>tmplength; write(tmpname,tmplength);break;cin>>tmpname;int insertpoint; cout<<“输入插入点:”< insert(tmpname,insertpoint);break;FAT[i]=0;case 2: cout<<“输入文件名:”< 信息工程学院计算机科学与技术082班 (3)运行结果 五、磁盘调度算法模拟 1.设计目的 (1)要求学生设计一个模拟磁盘调度的程序(2)理解磁盘调度过程中的三个时间段(3)理解磁盘调度的三种算法 信息工程学院计算机科学与技术082班 2.实验原理 共享设备的典型代表为磁盘,磁盘的物理块的地址由柱面号、磁道号、扇区号来指定,完成磁盘某一个物理块的访问要经过三个阶段:寻道时间 Ts、旋转延迟 Tw 和读写时间 Trw。 寻道时间 Ts 是磁头从当前磁道移动到目标磁道所需要的时间;旋转延迟 Tw 是当磁头停留在目标磁道后,目标物理块从当前位置旋转到磁头位置的时间;读写时间 Trw 是目标物理块内容与内存中对应交换的时间。磁盘调度的原则是公平和高吞吐量,衡量指标有访问时间 T 和平均访问时间 Ta: T=Ts+Tw+Trw Ta=Tsa+Twa+Trwa 寻道时间和旋转延迟成为调度算法的主要考虑因素。减少访问时间就是要减少寻道时间和旋转延迟。 3.设计要求 (1)设计并实现一个函数,完成先来先服务的磁盘调度功能 (2)设计并实现一个函数完成最短寻道时间优先的磁盘调度功能。(3)设计并实现一个函数完成电梯算法的磁盘调度功能。 信息工程学院计算机科学与技术082班 4、模拟算法的实现 (1)各算法流程图 先来先服务算法 Begin输入当前磁道号now磁头移动距离Sum=abs(now-array[0])磁头总移动距离Sum+=abs(array[j]-array[i])输出磁盘调度序列Array[j]N目前的位置变为当前的位置j++J 信息工程学院计算机科学与技术082班 最短寻道时间优先算法流程图 Begin奖磁道从小到大排序输入当前磁道号nowArray[m-1]<=now?输出磁盘调度序列array[j]Array[0]>=now?磁头移动总距离Sum=now-array[i]输出磁盘调度序列array[j]确定当前磁道在已排的序列中的位置目前的位置变为当前的位置now=array[i]磁头移动的总距离Now-array[l]<=array[r]-now?先向磁道号减小方向访问,再向磁道号增加方向访问先向磁道号增加方向访问,再向磁道号减小方向访问目前为止变为当前的位置now=array[i]i>=0i (2)程序代码 #include int j,i,now;float sum = 0,avg; cout<<“输入当前的磁道号:”;//输入当前磁道号 信息工程学院计算机科学与技术082班 cin>>now;sum=abs(now-array[0]); cout<<“先来先服务算法调度后的序列为”< for(i=0,j=1;j sum=sum+abs(array[j]-array[i]); cout< //输出磁盘调度序列 } avg=sum/(m); cout< int temp; int k=1; int now,l,r; int i,j; float sum=0,avg=0; for(i=0;i for(j=i+1;j { if(array[i]>array[j])//将磁道号从小到大排序 { temp=array[i]; array[i]=array[j]; array[j]=temp; } cout<<“请输入当前的磁道号:”;//输入当前磁道号 cin>>now; cout<<“最短寻道时间优先算法调度后的序列为”;//输出磁盘调度序列 if(array[m-1]<=now)//若被访问的下一最大的磁道号不大于当前的磁道号 { for(i=m-1;i>=0;i--) { cout< } else { if(array[0]>=now)//若被访问的下一最小的磁道号不小于当前的磁道号 { sum=now-array[i]; now=array[i];} } 信息工程学院计算机科学与技术082班 for(i=0;i { cout< sum=array[i]-now; } } { { k++; } now=array[i]; else //当前的磁道号的值在若所有被访问的下的磁道号之间 while(array[k] l=k-1; r=k; if((now-array[l])<=(array[r]-now)) { while(l>=0) //先向磁道号减小方向访问 { cout< sum=sum+now-array[l]; now=array[l]; l=l-1; } else //先向磁道号增加方向访问 { while(r } now=array[0]; for(j=r;j { cout< sum+=array[j]-now; } now=array[j]; { cout< sum+=array[r]-now; now=array[r]; r=r+1; } now=array[m-1]; for(j=l;j>=0;j--)//再向磁道号减小方向访问 { cout< sum+=now-array[j]; } now=array[j]; 信息工程学院计算机科学与技术082班 } avg=sum/(m); cout< int temp; int k=1; int now,d,l,r; int i,j; float sum=0,avg=0; for(i=0;i for(j=i+1;j { if(array[i]>array[j])//将磁道号从小到大排序 { temp=array[i]; array[i]=array[j]; array[j]=temp; } cout<<“请输入当前的磁道号:”;//输入当前磁道号 cin>>now; cout<<“请输入当前移动臂的移动的方向(1 表示向磁道号增加方向,0 表示向磁道号减小方向): ”; cin>>d; //先要给出当前磁道号和移动臂的移动方向 cout<<“电梯算法调度后的序列为”; if(array[m-1]<=now) //若被访问的下一最大的磁道号不大于当前的磁道号 { for(i=m-1;i>=0;i--) { cout< } else { if(array[0]>=now)//若被访问的下一最小的磁道号不小于当前的磁道号 { sum=now-array[i]; now=array[i];} } } } for(i=0;i { cout< sum=array[i]-now; 信息工程学院计算机科学与技术082班 } } { { k++; } now=array[i]; else //当前的磁道号的值在若所有被访问的下的磁道号之间 while(array[k] l=k-1; r=k; switch(d) { case 0: //先向磁道号减小方向访问 { while(l>=0) { cout< sum=sum+now-array[l]; now=array[l]; l=l-1; { while(r } now=array[0]; for(j=r;j { cout< sum+=array[j]-now; } break;} now=array[j]; case 1: //先向磁道号增加方向访问 { cout< sum+=array[r]-now; now=array[r]; r=r+1; } now=array[m-1]; for(j=l;j>=0;j--) { cout< sum+=now-array[j]; }break; now=array[j]; } 信息工程学院计算机科学与技术082班 } avg=sum/(m); cout< int i,m,n,flag=1,array[100]; cout<<“输入磁盘调度序列的个数:”; cin>>m; cout<<“分别输入磁盘调度序列:”;for(i=0;i cout<<“0 终止”< cout<<“1 先来先服务算法”< cout<<“2 最短寻道时间优先算法”< cout<<“3 电梯算法算法”< cout<<“选择以上的算法:”; } cin>>n;{ case 0: { flag=0;break;} //终止程序 case 1: } { FCFS(array,m);break;} //先来先服务算法 { SSTF(array,m);break;}//最短寻道时间优先算法 { SCAN(array,m);break;}//电梯算法 case 2: switch(n) default: cout<<“输入有误”< } } case 3: default: cout<<“输入有误,请重新输入:”< 信息工程学院计算机科学与技术082班 (3)运行结果 输入相关调度信息: 先来先服务算法: 最短寻道时间优先算法: 电梯算法: 六、总结 本人在刘发升老师的指导下,顺利完成该课程设计。通过此次课程设计,收获颇多。 一、对实验原理有更深的理解 通过模拟DOS的课程设计,掌握了DOS各项功能实现的根本原理。并通过把该算法的内容,算法的执行顺序在计算机上实现,把原来以为很深奥的书本知识变的更为简单,对实验原理有更深的理解。 二、对该理论在实践中的应用有深刻的理解 通过把该算法的内容,算法的执行顺序在计算机上实现,知道和理解了该理论在计算机中是怎样执行的,对该理论在实践中的应用有深刻的理解。 三、激发了学习的积极性 信息工程学院计算机科学与技术082班 通过此次课程设计,全面系统的理解了计算机操作系统中各项功能的一般原理和基本实现方法。把死板的课本知识变得生动有趣,激发了学习的积极性。把学过的计算机操作系统的知识强化,能够把课堂上学的知识通过自己设计的程序表示出来,加深了对理论知识的理解。以前对与计算机操作系统的认识是模糊的,概念上的,现在通过自己动手做实验,从实践上认识了操作系统是如何处理命令的,如何协调计算机内部各个部件运行。课程设计中程序比较复杂,在调试时应该仔细,在程序调试时,注意指针,将不必要的命令去除。在这次课程设计中,我就是按照实验指导的思想来完成。加深了理解文件系统的内部功能及内部实现,培养实践动手能力和程序开发能力的目的。 四、理解了该知识点以及学科之间的融合渗透 本次课程设计程序部分是用C语言编写的,把《计算机操作系统》和《C语言》两门门学科联系起来,把各个学科之间的知识融合起来,把各门课程的知识联系起来,对计算机整体的认识更加深刻。使我加深了对《计算机操作系统》和《C语言》课程的认识。同时对操作系统中各种功能的本质有了充分地了解。 《计算机操作系统》课程设计教学大纲 课程编号:08120070 课程名称:计算机操作系统/Computer Operating System 课程总学时/学分:56/3.(其中理论46学时,实验10学时 课程设计时间/学分:1周/1学分 适用专业:计算机科学与技术 一、设计任务及目的 《计算机操作系统》课程是计算机科学与技术专业的一门重要专业基础课,“计算机操作系统课程设计”的目的是在学生学习了《计算机操作系统》课程之后理论联系实践,一方面延续《计算机操作系统》课程实验的要求,进一步加深与巩固学生对计算机操作系统中概念、基本原理、算法的理解和掌握,培养学生对计算机常用操作系统的操作能力;另一方面通过本环节加强培养学生分析、修改和设计操作系统的能力。期望达到学为所用,并且能进一步提高使用计算机和编程能力。 二、课程设计的基本要求 1、了解所选择开发环境的调试功能,掌握跟踪,修改错误的技巧。 2、能根据实际问题选择数据结构,清淅的描述算法。 3、培养良好的编程风格。 4、撰写课程设计报告,按格式要求写出完整的、规范的报告并打印,其中模块图、流程图要清楚规范,特别要求学生独立完成。 三、设计需运用的基本理论 设计需运用计算机系统知识、操作系统基本概念、进程管理、存储管理技术、I/O管理技术、文件管理、高级语言程序设计、数据结构等内容。 四、课程设计内容与时间安排 1、设计内容:可以选择下面提供的参考选题,也可以自选,如果自选,需要将自选题,目的详细内容以及实现要求提供给老师,老师批准后方可采用。 课题一:进程管理演示 设计目的:加深对进程概念及进程管理各部分内容的理解;熟悉进程管理中主要数据结构的设计及进程调度算法、进程控制机构、同步机构及通讯机构的实施。 设计内容:设计一个允许n个进程并发运行的进程管理模拟系统。该系统包括有简单的进程控制、同步与通讯机构,其进程调度算法可任意选择(优先级调度,时间片轮转,短进程优先中的一种)。每个进程用一个PCB表示,其内容根据具体情况设置。各进程之间有一定的同步 关系(可选)。系统在运行过程中应能显示或打印各进程的状态及有关参数的变化情况,以便观察诸进程的运行过程及系统的管理过程。 课题二:存储管理系统设计 设计目的:使学生熟悉存储器管理系统的设计方法;加深对所学各种存储器管理方案的了解。设计内容:采用一些常用的存储器分配算法,设计一个请求页式存储管理模拟系统并调试运行。课题三:编程模拟银行家算法 设计目的:通过设计和调试银行家算法通用程序,加深对死锁概念和死锁避免方法的了解。设计内容:编制银行家算法程序,并检测所给状态的系统安全性。课题四:磁盘调度算法的实现与分析 设计目的:使学生熟悉磁盘管理系统的设计方法;加深对所学各种磁盘调度算法的了解及其算法的特点。 设计内容:编程序实现下述磁盘调度算法,并求出每种算法的平均移动磁道数,并分析结果: ①先来先服务算法(FCFS)②最短寻道时间优先算法(SSTF)③扫描算法(SCAN)④循环扫描算法(C-SCAN) 课题五:文件系统演示 设计目的:使学生熟悉文件管理系统的设计方法;加深对所学各种文件操作的了解及其操作方法的特点。 设计内容:设计一个简单的多用户文件系统。即 ①在系统中用一个文件来模拟一个磁盘; ②此系统至少有:Create、delete、open、close、read、write等和部分文件属性的功能。③实现这个文件系统。④能实际演示这个文件系统。 基本上是进入一个界面(此界面就是该文件系统的界面)后,可以实现设计的操作要求。 2、时间安排: 动员,准备及规则(0.5天) 具体内容:动员、选题、系统功能和需求的分析。 课程设计实施及检查(0.5天) 具体内容:任务规划,设计出每个功能 课程设计实施(5天) 具体内容:具体功能的实现、系统的完善、中期检查和个人答辩 整理课程设计报告书(1天) 具体内容:文档的整理,设计报告的完成 五、考核方式与评分办法 考核方式:课堂点名、设计报告及个人答辩的综合评定 评分方式:课程设计成绩=点名*10%+设计报告*60+答辩*30% 成绩实行五级记分。其中,优(90-100分),良(80-89),中(70-79),及格(60-69),不及格(59分及以下)。如果教师认定为抄袭,则成绩为0分。 六、使用教材及参考书(小4号黑体) [1]徐虹.操作系统实验指导.清华大学 出版社,2009年3月 [2]孟庆昌.操作系统(第2版).电子工业出版社,2010年9月 [3]罗宇,邹鹏等.操作系统(第2版).电子工业出版社,2007年 4月 [4]宗大华,宗涛等.操作系统.人民邮电出版社,2009年1月 执笔人:左新娥 2011年11月2日 审核人:文志强 2011年11月5日 批准人: 朱艳辉 2011年11月6日 《计算机操作系统》 课 程 设 计 报 告 题 目: 银行家算法 班 级: XXXXXXXXXXXXXXXX 姓 名: XXM 学 号: XXXXXXXXXXXX 指导老师: XXXXXXXXXXXXXX 设计时间: XXXXXXXXXXXXXXX 一.设计目的 1、掌握死锁概念、死锁发生的原因、死锁产生的必要条件; 2、掌握死锁的预防、死锁的避免; 3、深刻理解死锁的避免:安全状态和银行家算法; 二.银行家算法 1.简介 银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。 2.数据结构 1)可利用资源向量Available 是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。2)最大需求矩阵Max 这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。3)分配矩阵Allocation 这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的 数目为K。4)需求矩阵Need 这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。Need[i,j]=Max[i,j]-Allocation[i,j].3.算法原理 操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。 三.算法实现 1.初始化 由用户输入数据,分别对可利用资源向量矩阵AVAILABLE、最大需求矩阵MAX、分配矩阵ALLOCATION、需求矩阵NEED赋值。 2.银行家算法 在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。 银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。设进程cusneed提出请求REQUEST [i],则银行家算法按如下规则进行判断。(1)如果REQUEST [cusneed] [i]<= NEED[cusneed][i],则转(2);否则,出错。(2)如果REQUEST [cusneed] [i]<= AVAILABLE[cusneed][i],则转(3);否则,出错。(3)系统试探分配资源,修改相关数据: AVAILABLE[i]-=REQUEST[cusneed][i];ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];NEED[cusneed][i]-=REQUEST[cusneed][i];(4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。 3.安全性检查算法 (1)设置两个工作向量Work=AVAILABLE;FINISH(2)从进程集合中找到一个满足下述条件的进程,FINISH==false;NEED<=Work;如找到,执行(3);否则,执行(4)(3)设进程获得资源,可顺利执行,直至完成,从而释放资源。Work+=ALLOCATION;Finish=true;GOTO 2(4)如所有的进程Finish= true,则表示安全;否则系统不安全。 4.算法流程图 1)初始化算法流程图 2)银行家算法流程图: 3)安全性算法流程图: 4.代码(C语言) #include /*M个进程对N类资源最大资源需求量*/ int MAX[M][N]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};/*系统可用资源数*/ int AVAILABLE[N]={10,5,7};/*M个进程对N类资源最大资源需求量*/ int ALLOCATION[M][N]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; /*M个进程已经得到N类资源的资源量 */ int NEED[M][N]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}}; /*M个进程还需要N类资源的资源量*/ int Request[N]={0,0,0}; void main(){ int i=0,j=0;char flag; void showdata();void changdata(int);void rstordata(int);int chkerr(int);showdata();enter:{ printf(“请输入需申请资源的进程号(从0到”); printf(“%d”,M-1); printf(“):”); scanf(“%d”,&i);} if(i<0||i>=M){ printf(“输入的进程号不存在,重新输入!n”); goto enter;} err:{ printf(“请输入进程”); printf(“%d”,i); printf(“申请的资源数n”); printf(“类别: A B Cn”);printf(“ ”); for(j=0;j { scanf(“%d”,&Request[j]); if(Request[j]>NEED[i][j]) { printf(“%d”,i); printf(“号进程”); printf(“申请的资源数 > 进程”); printf(“%d”,i); printf(“还需要”); printf(“%d”,j);printf(“类资源的资源量!申请不合理,出错!请重新选择!n”); goto err; } else { if(Request[j]>AVAILABLE[j]) { printf(“进程 ”); printf(“%d”,i); printf(“申请的资源数大于系统可用”); printf(“%d”,j); printf(“类资源的资源量!申请不合理,出错!请重新选择!n”); goto err; } } } } changdata(i);if(chkerr(i)){ rstordata(i); showdata();} else showdata(); printf(“n”); printf(“按'y'或'Y'键继续,否则退出n”); flag=getch(); if(flag=='y'||flag=='Y'){ goto enter; } else { exit(0);} } /*显示数组*/ void showdata(){ int i,j;printf(“系统可用资源向量:n”);printf(“***Available***n”);printf(“资源类别: A B Cn”);printf(“资源数目:”);for(j=0;j printf(“%d ”,AVAILABLE[j]);} printf(“n”);printf(“n”);printf(“各进程还需要的资源量:n”);printf(“******Need******n”);printf(“资源类别: A B Cn”);for(i=0;i printf(“ ”); printf(“%d”,i); printf(“号进程:”); for(j=0;j { printf(“ %d ”,NEED[i][j]); } printf(“n”);} printf(“n”);printf(“各进程已经得到的资源量: n”);printf(“***Allocation***n”);printf(“资源类别: A B Cn”);for(i=0;i printf(“ ”); printf(“%d”,i); printf(“号进程:”); /*printf(“:n”);*/ for(j=0;j { printf(“ %d ”,ALLOCATION[i][j]); } printf(“n”); } printf(“n”);} /*系统对进程请求响应,资源向量改变*/ void changdata(int k){ int j; for(j=0;j AVAILABLE[j]=AVAILABLE[j]-Request[j]; ALLOCATION[k][j]=ALLOCATION[k][j]+Request[j]; NEED[k][j]=NEED[k][j]-Request[j];} } /*资源向量改变*/ void rstordata(int k) { int j; for(j=0;j AVAILABLE[j]=AVAILABLE[j]+Request [j]; ALLOCATION[k][j]=ALLOCATION[k][j]-Request[j]; NEED[k][j]=NEED[k][j]+Request[j]; } } /*安全性检查函数*/ int chkerr(int s){ int WORK,FINISH[M],temp[M];int i,j,k=0; for(i=0;i WORK=AVAILABLE[j]; i=s; printf(“n”); while(i { if(FINISH[i]==FALSE&&NEED[i][j]<=WORK) { printf(“系统不安全!本次资源申请不成功!n”); printf(“n”); return 1; } } } WORK=WORK+ALLOCATION[i][j]; FINISH[i]=TRUE; temp[k]=i;k++;i=0; printf(“n”); printf(“经安全性检查,系统安全,本printf(”n“); printf(” 本次安全序列:n“);printf(”进程依次为“);for(i=0;i printf(”%d“,temp[i]); 次分配成功。n”);} else { i++;} } for(i=0;i printf(“-> ”);} printf(“n”);return 0;四.程序运行截图 0号进程申请资源{1,2,3},各向量发生变化 0和进程继续申请资源{2,2,0},各向量变化 2号进程申请资源,由于NEED[2]={9,0,2},前两次申请不合理,系统处于不安全状态太。第三次2号申请资源向量为{1,0,2},系统回到安全状态,并得出新的安全序列3-0-1-2-4。 五.心得体会 从此次的课程设计中,我收获很多。首先也是最重要的一点是对处理机调度与死锁有了深入的理解;其次,再次巩固了C语言编程。 在用C语言设计和编写银行家算法和安全性检查算法时遇到了一些困难都克服了。在使程序界面美观、能够持续循环运行时用了很多方法,花了比较多的时间。最后选择用goto语句控制,我觉得在此实验中比较好,代码阅读起来更加方便。 课程设计报告 题 目: 模拟请求页式管理 课程名称: 计算机操作系统 学 院: 信息工程学院 专 业: 计算机科学与技术 班 级: 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';} } } 操 作 系 统 课 程 设 计 实 验 报 告 学院:计算机科学与技术学院 班级:计112 学号:1113022032 姓名: 一、实验名称: 用C++实现驱动调度算法、页面替换算法、银行家算法、处理器调度算法 二、实验要求: 书写实验报告,包括的内容有: (1)实验题目 (2)程序中使用的数据结构及主要文字说明 (3)带有注释的源程序 (4)执行程序说明,表明各进程控制快的初始状态,以及各算法的运行状态 (5)通过实验后的收获与体会及对实验的改进意见和见解 二、实验目的: 通过自己编程来实现各类操作系统算法,进一步理解操作系统的概念及含义,提高对操作系统的认识,同时提高自己的动手实践能力。加强我们对各类算法的理解。 三、实验内容: 1、实现页面替换算法 (1)FIFO 先进先出页面替换算法 (2)LRU最近最少使用页面替换算法 (3)LFU最少使用频率页面替换算法 2、银行家算法 3、实现驱动调度算法 (1)先来先服务算法 (2)电梯算法 (3)扫描算法 4、实现处理器调度 (1)先进先出处理器调度 (2)时间片轮转法 (3)优先级调度 四、实验原理: 1、页面替换算法 先进先出页面置换算法:该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面加以淘汰。将已调入内存的页面按先后次序链接成一个队列,将最先调入的页面与新页面进行置换 最近最久未使用置换算法:该算法是利用“最近的过去”作为“最近的将来”,将最近最久未使用的页面加以淘汰。将已调入内存的页面按先后顺序链接成一个队列,为每一个页面增加一个访问字段,用来记录一个页面自上次被访问以来所经历的是时间t,当需淘汰一个页面时,选择现有页面中其t值最大,即最近最久未使用的页面加以淘汰 2、银行家算法 先对用户提出的请求进行合法性检查,即检查请求的是不大于需要的,是否不大于可利用的。若请求合法,则进行试分配。最后对试分配后的状态调用安全性检查算法进行安全性检查。若安全,则分配,否则,不分配,恢复原来状态,拒绝申请。 3、驱动调度算法 先进先出算法(FIFO):总是严格按时间顺序对磁盘请求予以处理。算法实现简单、易于理解并且相对公平,不会发生进程饿死现象。但该算法可能会移动的柱面数较多并且会 经常更换移动方向,效率有待提高 电梯调度算法:总是将一个方向上的请求全部处理完后,才改变方向继续处理其他请求。 扫描算法(scan algorithm):总是从最外向最内(或最内向最外)进行扫描,然后在从最内向最外(或最外向最内)扫描。该算法与电梯调度算法的区别是电梯调度在没有最外或最内的请求时不会移动到最外或最内柱面。 4、处理器调度算法 先进先出处理器调度:按照作业进入系统后备工作队列的先后次序来挑选作业,先进入系统的作业将优先被挑选进入主存,创建用户进程,分配所需资源,然后移入就绪队列。 时间片轮转法调度算法:调度次序每次把CPU分配给就绪队列进程/线程使用规 定的时间间隔,就绪队列中每个进程/线程轮流的运行一个时间片,当时间片耗尽时,就强迫当前运行进程/线程让出处理器,转而排列到就绪队列尾部,等候下一轮调度。 优先级调度:根据确定的优先级来选取进程/线程,总是选择就绪队列中的优先 级最高者投入运行,即优先级越高,先被调用。 五、数据结构设计 对操作系统的各类算法设计数据结构如下: 页面替换算法:void FIFO();void LRU();void LFU(); 银行家算法:void Init()初始化算法 void Bank()银行家算法 bool Safe()安全性算法 驱动调度算法: struct MagneticHead//磁头构成{ int site; int count; bool direct; }; struct Range//磁盘磁道范围 { int mStart; int mEnd; }; struct RequestList//请求序列 { int site; bool state; }; struct Data//基本数据集合{ MagneticHead magneticHead; RequestList *requestList; int *executeList; Range range; int length; }; 处理器调度: typedef struct pcb//时间片轮转法 { char pname[N]; int runtime; int arrivetime; char state; struct pcb*next; }PCB; typedef struct PCB1//先进先出服务 { char ID[3];//进程号 char name[10];//进程名 char state;//运行状态 floatarrivetime;//到达时间 floatstarttime;//进程开始时间 floatfinishtime;//进程结束时间 floatservicetime;//服务时间 float turnaroundtime;//周转时间 float weightedturnaroundtime;//带权周转时间 struct PCB1 *next;//指向下个进程 }pcb1; struct pcb2 {优先级调度 char name[10]; char state; int super; int ntime; int rtime; struct pcb2* link; }*ready=NULL,*d; typedef struct pcb2 PCB2; 六、课程设计总结 在本次课程设计中,就是讲平时所做的实验结合起来,实现操作系统的各类算法,了解操作系统的运行原理以及其基本概念,更好的将操作系统的原理很好的展现出来。同时,在本次实验中遇到了很多问题,需要我们仔细的检查和修改。其次,实验中为了能更好的体现各类算法的运行情况,需要做一个清晰的界面,以能清楚地看出运行结果。第二篇:计算机操作系统课程设计教学大纲
第三篇:计算机操作系统 课程设计报告 银行家算法
第四篇:操作系统课程设计报告
第五篇:操作系统课程设计报告