操作系统原理及安全课程设计

本文介绍了模拟处理器调度的三种算法:先来先服务(FCFS)、最短作业优先(SJF)和优先级调度,并通过具体代码实现展示了算法过程。此外,还详细探讨了磁盘调度的FCFS、SSTF和电梯调度算法,通过代码演示了不同算法的执行步骤和结果。
摘要由CSDN通过智能技术生成

1题:

  1. 题目分析:

利用线程和信号量知识,在Linux系统环境下,解决生产者消费者问题。

桌上有个能盛得下一个水果的空盘子。爸爸不停地向盘中放苹果或梨子,儿子不停地从盘中取出梨子享用,女儿不停地从盘中取出苹果享用。规定三人不能同时从盘子中取放水果。试用信号量实现爸爸、儿子和女儿这三个循环进程之间的同步。

测试数据假设父亲放置6次。

 

 2)整体设计:

  建立名为struvt的结构体,里面包括与题目有关的变量,例如记录盘中水果总数,盘中梨子个数苹果个数等等。通过调用该结构体的各个变量来实现表示数据和存储数据。使用数组存储数据。

typedef struct{

    int empty;

    struct process *L;

}ss;

void P(int *mutex){

    (*mutex)--;

}

void V(int *mutex){

(*mutex)++;

int apple=0,orange=0,num=0;

}

3)详细设计及实现:

#include <stdio.h>
#include <stdlib.h>

typedef int semaphore;

struct process{
};

typedef struct{
    int empty;
    struct process *L;
}ss;

void P(int *mutex){
    (*mutex)--;
}

void V(int *mutex){
    (*mutex)++;
}

int apple=0,orange=0,num=0;

void father(int *mutex){
     P(mutex);
     if(num<5){
            int b;
            b=rand()%2;
            if(b==0){
                apple++;
                num++;
                printf("爸爸放入一个苹果,现在盆子里有%d个水果,其中苹果有%d个,梨有%d个\n",num,apple,orange);

                }
            else{
                orange++;
                num++;
                printf("爸爸放入一个桔子,现在盆子里有%d个水果,其中苹果有%d个,梨有%d个\n",num,apple,orange);
                }
        }
     else
        printf("爸爸操作失败,盆子里已经有5个水果,其中有%d个苹果,%d个梨\n",apple,orange);
    V(mutex);
}

//女儿进程
void daughter(int *mutex){
    P(mutex);
    if(apple>0){
        apple--;
        num--;
        printf("女儿拿了一个苹果,盆子里还有%d个水果,其中苹果有%d个,梨有%d个\n",num,apple,orange);
    }else
        printf("女儿拿取失败,盆子里有%d个水果,其中苹果有%d个,梨有%d个\n",num,apple,orange);
    V(mutex);
}

//儿子进程
void son(int *mutex){
     P(mutex);
     if(orange>0){
         orange--;
         num--;
         printf("儿子拿了一个桔子,盆子里还有%d个水果,其中苹果有%d个,梨有%d个\n",num,apple,orange);
        }
    else
        printf("儿子拿取失败,盆子里有%d个水果,其中苹果有%d个,梨有%d个\n",num,apple,orange);
     V(mutex);
}

int main(){
    semaphore mutex=1;
    int n,a;
    printf("请输入你要运行的次数:");
    scanf("%d",&n);
    while(n--){
        a=rand()%3;
        if(a==0){
            printf("爸爸进行操作\n");
            father(&mutex);
            printf("\n");
        }else if(a==1){
            printf("女儿进行操作\n");
            daughter(&mutex);
            printf("\n");
        }else{
            printf("儿子进行操作\n");
            son(&mutex);
            printf("\n");}
}
return 0;
}

4)运行测试:

 

 

5)总结:

 主要说明:

 完成了哪些基本要求,完成情况;

完成了全部的基本要求,实现了题目要求的输出。

 完成哪些基本要求,说明原因;

完成全部要求,没有未完成的要求

 到了哪些困难,怎么解决;

(1)问题:竞争阶段三人争夺信号量问题解决很麻烦,最后使用&mutex变量归属来解决。

无扩充其他的功能。

(2问题:linux系统相关操作命令还不是很熟练,查阅了一些资料进行了解决。

系统的特色:代码简单易懂,运行速度快,运行界面简洁明了,易于查看。

第2题:

1题目分析

1.题目:

模拟处理器调度进程,实现以下算法:

有五个批处理作业JOB1、JOB2、JOB3、JOB4、JOB5,分别在0、1、3、5、6时刻到达系统。假设它们的预计运行时间分别为3、5、2、3、2,它们的优先数分别为5、3、1、2、6(设1为最低优先数)。该系统采用多道程序设计技术,且作业在执行过程中不进行I/O处理和系统调用,请分别采用"先来先服务调度算法"、"最短作业优先调度算法"和"优先数调度算法等三种算法,计算所有作业的平均周转时间和平均带权周转时间。忽略进程切换产生的系统开销。

作业序列如下表所示∶

 

2.算法描述:

(1)先来先服务算法:

FCFS是最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,系统将按照作业到达的先后次序来进行调度,或者说它是优先考虑在系统中等待时间最长的作业,而不管该作业所需执行时间的长短,从后备作业队列中选择几个最先进入该队列的作业,将它们调入内存,为它们分配资源和创建进程。然后把它放入就绪队列。当在进程调度中采用FCFS算法时,每次调度是从就绪的进程队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后,进程调度程序才将处理机分配给其它进程。

(2)最短作业优先调度算法:

SJF算法是以作业的长短来计算优先级,作业越短,其优先级越高。作业的长短是以作业所要求的运行时间来衡量的。SJF算法可以分别用于作业调度和进程调度。在把短作业优先调度算法用于作业调度时,它将从外存的作业后备队列中选择若干个估计运行时间最短的作业,优先将它们调入内存运行。

(3)优先数调度算法:

在优先级调度算法中,是基于作业的紧迫程度,由外部赋予作业相应的优先级,调度算法是根据该优先级进行调度的。这样就可以保证紧迫性作业优先运行。优先级调度算法可作为作业调度算法,也可作为进程调度算法。当把该算法用于作业调度时,系统是从后备队列中选择若干个优先级最高的作业装入内存。

3.流程图:

(1)先来先服务算法流程图:

 

(2)最短作业优先调度算法流程图:

 

(3)优先数调度算法流程图:

 

2系统总体设计

1. 数据结构设计:即怎么表示数据,如何存储数据?用数组还是链表,数据结构体怎么定义的

(1)先来先服务算法:

建立名为Job结构体,里面包括6个与作业有关的变量,例如作业的名字,作业到达系统的时间,作业服务时间等等。通过调用该结构体的各个变量来实现表示数据和存储数据。使用数组存储数据。

typedef struct job{

    char name[5];      //作业的名字

    int starttime;      //作业到达系统时间

    int needtime;       //作业服务时间

    int runtime;        //作业周转时间

    int endtime;        //作业结束时间

    double dqzz_time;    //带权周转时间

}Job;//定义结构体包含有以上6个变量

(2)最短作业优先调度算法:

建立名为Job结构体,里面包括6个与作业有关的变量,例如作业的名字,作业到达系统的时间,作业服务时间等等。通过调用该结构体的各个变量来实现表示数据和存储数据。使用数组存储数据。

typedef struct job{

    char name[5];      //作业的名字

    int starttime;      //作业到达系统时间

    int needtime;       //作业服务时间

    int runtime;        //作业周转时间

    int endtime;        //作业结束时间

    double dqzz_time;    //带权周转时间

}Job;//定义结构体包含有以上6个变量

(3)优先数调度算法:

建立名为Job结构体,里面包括7个与作业有关的变量,例如作业的名字,作业到达系统的时间,作业服务时间,作业的优先数等等。通过调用该结构体的各个变量来实现表示数据和存储数据。使用数组存储数据。

typedef struct job{

    char name[5];      //作业的名字

    int starttime;      //作业到达系统时间

    int needtime;       //作业服务时间

    int priority;        //作业优先级

    int runtime;        //作业周转时间

    int endtime;        //作业结束时间

    double dqzz_time;    //带权周转时间

}Job;//定义结构体包含有以上7个变量

2. 要求列出所有编写的函数清单,说明每个函数的功能,各形式参数的意义

(1)先来先服务算法:

void FCFS(Job job[],int n);//FCFS算法,算出各个作业的周转时间,结束时间和带权周转时间。job是包含作业各种数据的结构体,n表示作业的总数。

void init(Job job[],int starttime[],int needtime[],int n);//初始化结构里的变量。job是包含作业各种数据的结构体,starttime是记录作业进入系统的时间,needtime是记录作业运行所需的时间。

void Print(Job job[],int n);//统计总的周转时间和带权周转时间,以此算出平均周转时间和带权周转时间,并输出各个作业的周转时间和带权周转时间。job是包含作业各种数据的结构体,n表示作业的总数。

int main():主函数调用其他函数

(2)最短作业优先调度算法:

void SJF(Job job[],int n);//SJF算法,先按时间顺序进行排序,然后在此基础上已经到达的作业中运行时间较短的先访问。job是包含作业各种数据的结构体,n表示作业的总数。

void init(Job job[],int starttime[],int needtime[],int n);//初始化结构里的变量。job是包含作业各种数据的结构体,starttime是记录作业进入系统的时间,needtime是记录作业运行所需的时间。

void print(Job job[],int n);//统计总的周转时间和带权周转时间,以此算出平均周转时间和带权周转时间,并输出各个作业的周转时间和带权周转时间。job是包含作业各种数据的结构体,n表示作业的总数。

int main():主函数调用其他函数

(3)优先数调度算法:

void yxj(Job job[],int n);//优先级算法,先按时间顺序进行排序,然后在此基础上已经到达的作业中优先级较大的先访问。job是包含作业各种数据的结构体,n表示作业的总数。

void init(Job job[],int starttime[],int needtime[],int priority[],int n);//初始化结构里的变量。job是包含作业各种数据的结构体,starttime是记录作业进入系统的时间,needtime是记录作业运行所需的时间,priority是记录作业的优先数,优先数大的作业先被调用。

void print(Job job[],int n);//统计总的周转时间和带权周转时间,以此算出平均周转时间和带权周转时间,并输出各个作业的周转时间和带权周转时间。job是包含作业各种数据的结构体,n表示作业的总数。

int main():主函数调用其他函数

3. 系统界面设计:给出操作界面并说明

说明:代码开始运行,输出作业的平均周转时间和平均带权周转时间,然后再根据页面调用的顺序输出各个作业的作业名,周转时间和带权周转时间。

 

3系统详细设计及实现

   写出主函数和每个子函数的实现代码。主函数和子函数必须有注释。

(1)先来先服务算法:

#include<stdio.h>

#include<string.h>

typedef struct job{

    char name[5];      //作业的名字

    int starttime;      //作业到达系统时间

    int needtime;       //作业服务时间

    int runtime;        //作业周转时间

    int endtime;        //作业结束时间

    double dqzz_time;    //带权周转时间

}Job;//定义结构体包含有以上6个变量

void FCFS(Job job[],int n);//FCFS算法,算出各个作业的周转时间,结束时间和带权周转时间

void init(Job job[],int starttime[],int needtime[],int n);//初始化结构里的变量

void Print(Job job[],int n);//统计总的周转时间和带权周转时间,以此算出平均周转时间和带权周转时间,并输出各个作业的周转时间和带权周转时间

int main(){

    Job job[5];

    int starttime[5]={0,1,3,5,6};//各个作业的开始时间

    int needtime[5]={3,5,2,3,2};//各个作业的运行时间

init(job,starttime,needtime,5);

FCFS(job,5);

Print(job,5);

return 0;

}

void init(Job job[],int starttime[],int needtime[],int n){//初始化结构里的变量

int i;

strcpy(job[0].name,"JOB1");//为结构体中的变量赋值

strcpy(job[1].name,"JOB2");

strcpy(job[2].name,"JOB3");

strcpy(job[3].name,"JOB4");

strcpy(job[4].name,"JOB5");

for(i=0;i<n;i++){

job[i].starttime=starttime[i];

job[i].needtime=needtime[i];

}

}

void FCFS(Job job[],int n){//FCFS算法,算出各个作业的周转时间,结束时间和带权周转时间

int i,j;

char tempname[5]; //暂时保存作业名

int temptime;       //暂时保存数据     

for(i=0;i<n;i++){ //按作业到达系统时间进行排序,最早到达的排在最前面

for(j=i;j<n;j++){

if(job[j].starttime<job[i].starttime){   

temptime=job[j].starttime; //把到达时间早的赋值到temptime

job[j].starttime=job[i].starttime;

job[i].starttime=temptime;   

temptime=job[j].needtime;  //按照上面的顺序将运行时间与开始时间一一对应

job[j].needtime=job[i].needtime;

job[i].needtime=temptime;

strcpy(tempname,job[j].name); //对应将作业名与开始时间一一对应

     strcpy(job[j].name,job[i].name);

strcpy(job[i].name,tempname);

}

}

}  

for(i=0;i<n;i++){

if(i==0){      //第一个作业

    job[i].runtime=job[i].needtime;          //周转时间=服务时间

    job[i].endtime=job[i].starttime+job[i].needtime;     //结束时间=到达时间+服务时间    

    }

else if(job[i].starttime>job[i-1].endtime){  //第i个进程到达系统时,第i-1个进程已运行完毕

    job[i].runtime=job[i].needtime;   //周转时间=服务时间

    job[i].endtime=job[i].starttime+job[i].needtime;   //结束时间=到达时间+服务时间

}

else{                              //第i个进程到达系统时,第i-1个进程未运行完毕

    job[i].runtime=job[i].needtime+job[i-1].endtime-job[i].starttime; //周转时间=服务时间+前一个的结束时间-到达时间

    job[i].endtime=job[i].starttime+job[i].runtime;  //结束时间=到达时间+周转时间

}

job[i].dqzz_time=job[i].runtime*1.0/job[i].needtime;//带权周转时间=周转时间/服务时间,数据型转变

}

}

void Print(Job job[],int n){//统计总的周转时间和带权周转时间,以此算出平均周转时间和带权周转时间,并输出各个作业的周转时间和带权周转时间

    int i;

    double avertime;

    double dqzz_avertime;

    int sum_runtime=0;

    double  sum_dqzztime=0.0;

    printf("FIFS:");

    for(i=0;i<n;i++){

     sum_runtime=sum_runtime+job[i].runtime;//总时间等于各个作业周转时间的总和

     sum_dqzztime=sum_dqzztime+job[i].dqzz_time;//总带权周转时间等于各个作业带权周转时间的总和

    }

    avertime=sum_runtime*1.0/n;//计算平均周转时间 ,数据型转变

    dqzz_avertime=sum_dqzztime*1.000/n;//计算平均带权周转时间 ,数据型转变

    printf("T:%.2g    ",avertime);

    printf("W:%.2g\n",dqzz_avertime);

    printf("作业名  周转时间 带权周转时间\n");

    for(i=0;i<n;i++){

     printf("%s       %d        %.2g\n",job[i].name,job[i].runtime,job[i].dqzz_time);//输出各个作业的周转时间和带权周转时间

    }

}

(2)最短作业优先调度算法:

#include<stdio.h>

#include<string.h>

typedef struct job{

    char name[5];      //作业的名字

    int starttime;      //作业到达系统时间

    int needtime;       //作业服务时间

    int runtime;        //作业周转时间

    int endtime;        //作业结束时间

    double dqzz_time;    //带权周转时间

}Job;//定义结构体包含有以上6个变量

void SJF(Job job[],int n);//SJF算法,先按时间顺序进行排序,然后在此基础上已经到达的作业中运行时间较短的先访问

void init(Job job[],int starttime[],int needtime[],int n);//初始化结构里的变量

void print(Job job[],int n);//统计总的周转时间和带权周转时间,以此算出平均周转时间和带权周转时间,并输出各个作业的周转时间和带权周转时间

int main(){

    Job job[5];

    int starttime[5]={0,1,3,5,6};//各个作业的开始时间

    int needtime[5]={3,5,2,3,2};//各个作业的运行时间

init(job,starttime,needtime,5);

SJF(job,5);

print(job,5);

}

void init(Job job[],int starttime[],int needtime[],int n){//初始化结构里的变量

int i;

strcpy(job[0].name,"JOB1");//为结构体中的变量赋值

strcpy(job[1].name,"JOB2");

strcpy(job[2].name,"JOB3");

strcpy(job[3].name,"JOB4");

strcpy(job[4].name,"JOB5");

for(i=0;i<n;i++){

job[i].starttime=starttime[i];

job[i].needtime=needtime[i];

}

}

void SJF(Job job[],int n){//SJF算法,先按时间顺序进行排序,然后在此基础上已经到达的作业中运行时间较短的先访问

    int i,j;

    char tempname[10];//暂时保存作业名

    int temptime;   //暂时保存数据

for(i=0;i<n;i++){ //按作业到达系统时间进行排序,最早到达的排在最前面

for(j=i;j<n;j++){

if(job[j].starttime<job[i].starttime){   

temptime=job[j].starttime; //把到达时间早的赋值到temptime

job[j].starttime=job[i].starttime;

job[i].starttime=temptime;   

temptime=job[j].needtime;  //按照上面的顺序将运行时间与开始时间一一对应

job[j].needtime=job[i].needtime;

job[i].needtime=temptime;

strcpy(tempname,job[j].name); //对应将作业名与开始时间一一对应

      strcpy(job[j].name,job[i].name);

strcpy(job[i].name,tempname);

}

}

}   

//第一个到达的作业                     

job[0].endtime=job[0].starttime+job[0].needtime; //结束时间=到达时间+服务时间

    job[0].runtime=job[0].needtime; //周转时间=服务时间

    job[0].dqzz_time=job[0].runtime*1.0/job[0].needtime; //带权周转时间=周转时间/服务时间

    for(i=1;i<n;i++){

for(j=i+1;j<n;j++){

if(job[i-1].endtime>job[i].starttime&&job[i-1].endtime<job[j].starttime){

break;

}

if(job[i-1].endtime>job[i].starttime&&job[j].needtime<job[i].needtime){ //前一个作业结束前新的作业已经到达,且新作业后面的作业周转时间小于新的作业

temptime=job[i].starttime;//把到达时间早的赋值到temptime

job[i].starttime=job[j].starttime;

job[j].starttime=temptime;

   

temptime=job[i].needtime;//按照上面的顺序将运行时间与开始时间一一对应

job[i].needtime=job[j].needtime;

job[j].needtime=temptime;



strcpy(tempname,job[i].name);   //将第二个参数的值复制给第一个参数,返回第一个参数

strcpy(job[i].name,job[j].name);

strcpy(job[j].name,tempname);

}                 //按最短运行时间排序

}

if(job[i].starttime>job[i-1].endtime){                  //第i个进程到达系统时,第i-1个进程已运行完毕

job[i].endtime=job[i].starttime+job[i].needtime; //结束时间=开始时间+运行时间

job[i].runtime=job[i].needtime;//周转时间=运行时间

}

else{

job[i].endtime=job[i-1].endtime+job[i].needtime;//结束时间=前一个作业的结束时间+运行时间

job[i].runtime=job[i].endtime-job[i].starttime; //周转时间=结束时间-开始时间

}

job[i].dqzz_time=job[i].runtime*1.0/job[i].needtime;

}

}

void print(Job job[5],int n){//统计总的周转时间和带权周转时间,以此算出平均周转时间和带权周转时间,并输出各个作业的周转时间和带权周转时间

int i;

    double avertime;

    double dqzz_avertime;

    int sum_runtime=0;

    double  sum_dqzztime=0.00;

    printf("SJF:");

    for(i=0;i<n;i++){

     sum_runtime=sum_runtime+job[i].runtime;//总时间等于各个作业周转时间的总和

     sum_dqzztime=sum_dqzztime+job[i].dqzz_time;//总带权周转时间等于各个作业带权周转时间的总和

    }

    avertime=sum_runtime*1.0/n;//计算平均周转时间 ,数据型转变

    dqzz_avertime=sum_dqzztime*1.000/n;//计算平均带权周转时间 ,数据型转变

    printf("T:%.2g   ",avertime);

    printf("W:%.2g \n",dqzz_avertime);

    printf("作业名  周转时间 带权周转时间\n");

    for(i=0;i<n;i++){

     printf("%s       %2d       %.2g\n",job[i].name,job[i].runtime,job[i].dqzz_time);//输出各个作业的周转时间和带权周转时间

    }

}

(3)优先数调度算法:

#include<stdio.h>

#include<string.h>

typedef struct job{

    char name[5];      //作业的名字

    int starttime;      //作业到达系统时间

    int needtime;       //作业服务时间

    int priority;        //作业优先级

    int runtime;        //作业周转时间

    int endtime;        //作业结束时间

    double dqzz_time;    //带权周转时间

}Job;//定义结构体包含有以上7个变量

void yxj(Job job[],int n);//优先级算法,先按时间顺序进行排序,然后在此基础上已经到达的作业中优先级较大的先访问

void init(Job job[],int starttime[],int needtime[],int priority[],int n);//初始化结构里的变量

void print(Job job[],int n);//统计总的周转时间和带权周转时间,以此算出平均周转时间和带权周转时间,并输出各个作业的周转时间和带权周转时间

int main(){

    Job job[5];

    int starttime[5]={0,1,3,5,6};//各个作业的开始时间

    int needtime[5]={3,5,2,3,2};//各个作业的运行时间

    int priority[5]={5,3,1,2,6};//各个作业的优先级

init(job,starttime,needtime,priority,5);

yxj(job,5);

print(job,5);

}

void init(Job job[],int starttime[],int needtime[],int priority[],int n){//初始化结构里的变量

int i;

strcpy(job[0].name,"JOB1");//为结构体中的变量赋值

strcpy(job[1].name,"JOB2");

strcpy(job[2].name,"JOB3");

strcpy(job[3].name,"JOB4");

strcpy(job[4].name,"JOB5");

for(i=0;i<n;i++){

job[i].starttime=starttime[i];

job[i].needtime=needtime[i];

job[i].priority=priority[i];

}

}

void yxj(Job job[],int n){//优先级算法,先按时间顺序进行排序,然后在此基础上已经到达的作业中优先级较大的先访问

    int i,j;

    char tempname[10];

    int temptime;  

for(i=0;i<n;i++){ //按作业到达系统时间进行排序,最早到达的排在最前面

for(j=i+1;j<n;j++){

if(job[j].starttime<job[i].starttime){   

temptime=job[j].starttime; //把到达时间早的赋值到temptime

job[j].starttime=job[i].starttime;

job[i].starttime=temptime;   

temptime=job[j].needtime;  //按照上面的顺序将运行时间与开始时间一一对应

job[j].needtime=job[i].needtime;

job[i].needtime=temptime;

temptime=job[j].priority;  //按照上面的顺序将优先级与开始时间一一对应

job[j].priority=job[i].priority;

job[i].priority=temptime;

strcpy(tempname,job[j].name); //对应将作业名与开始时间一一对应

     strcpy(job[j].name,job[i].name);

strcpy(job[i].name,tempname);

}

}

}   

//第一个到达的作业                     

job[0].endtime=job[0].starttime+job[0].needtime; //结束时间=到达时间+服务时间

    job[0].runtime=job[0].needtime; //周转时间=服务时间

    job[0].dqzz_time=job[0].runtime*1.0/job[0].needtime; //带权周转时间=周转时间/服务时间

    for(i=1;i<n;i++){

for(j=i;j<n;j++){

if(job[i-1].endtime>job[i].starttime&&job[i-1].endtime<job[j].starttime){

break;

}

if(job[i-1].endtime>job[i].starttime&&job[j].priority>job[i].priority){ //前一个作业结束前新的作业已经到达,且新作业后面的作业优先级小于新的作业

temptime=job[i].starttime;//把到达时间早的赋值到temptime

job[i].starttime=job[j].starttime;

job[j].starttime=temptime;

   

temptime=job[i].needtime;//按照上面的顺序将运行时间与开始时间一一对应

job[i].needtime=job[j].needtime;

job[j].needtime=temptime;



                temptime=job[j].priority;  //按照上面的顺序将优先级与开始时间一一对应

job[j].priority=job[i].priority;

job[i].priority=temptime;



strcpy(tempname,job[i].name);   //将第二个参数的值复制给第一个参数,返回第一个参数

strcpy(job[i].name,job[j].name);

strcpy(job[j].name,tempname);

}                 //按最短运行时间排序

}

if(job[i].starttime>job[i-1].endtime){                  //第i个进程到达系统时,第i-1个进程已运行完毕

job[i].endtime=job[i].starttime+job[i].needtime; //结束时间=开始时间+运行时间

job[i].runtime=job[i].needtime;//周转时间=运行时间

}

else{

job[i].endtime=job[i-1].endtime+job[i].needtime;//结束时间=前一个作业的结束时间+运行时间

job[i].runtime=job[i].endtime-job[i].starttime; //周转时间=结束时间-开始时间

}

job[i].dqzz_time=job[i].runtime*1.0/job[i].needtime;

}

}

void print(Job job[5],int n){//统计总的周转时间和带权周转时间,以此算出平均周转时间和带权周转时间,并输出各个作业的周转时间和带权周转时间

int i;

    double avertime;

    double dqzz_avertime;

    int sum_runtime=0;

    double  sum_dqzztime=0.00;

    printf("SJF:");

    for(i=0;i<n;i++){

     sum_runtime=sum_runtime+job[i].runtime;//总时间等于各个作业周转时间的总和

     sum_dqzztime=sum_dqzztime+job[i].dqzz_time;//总带权周转时间等于各个作业带权周转时间的总和

    }

    avertime=sum_runtime*1.0/n;//计算平均周转时间 ,数据型转变

    dqzz_avertime=sum_dqzztime*1.000/n;//计算平均带权周转时间 ,数据型转变

    printf("T:%.2g   ",avertime);

    printf("W:%.2g \n",dqzz_avertime);

    printf("作业名  周转时间 带权周转时间\n");

    for(i=0;i<n;i++){

     printf("%s       %2d       %.2g\n",job[i].name,job[i].runtime,job[i].dqzz_time);//输出各个作业的周转时间和带权周转时间

    }

}

4运行测试

   (运行效果截图,要针对程序处理的不同情况列出有代表性的输入和输出,用足够多的实例说明程序完成了设计任务和目标。)

 设计测试数据,并输入,给出运行结果

(1)先来先服务算法:

 

(2)最短作业优先调度算法:

 

(3)优先数调度算法:

 

5总结

主要说明:

1.已经完成了哪些基本要求,完成情况;

实现了先来先服务算法,最短作业优先调度算法和优先数调度算法,完成了全部要求,实现题目要求的输出情况。

2.未完成哪些基本要求,说明原因;

全部实现,没有未完成的要求。

3.遇到了哪些困难,怎么解决;

(1)问题:对结构体的变量赋值,字符串不知道该如何像其他整型变量一样通过for循环和数组进行实现。

解决方法:使用strcpy()函数,一个一个对其赋值。

(2)问题:将运行时间较短的作业调整到前面运行的时候,可能出现前一个作业结束了,但是运行时间较短的作业还未到达系统的情况

解决方法:在循环时加入job[i-1].endtime>job[i].starttime&&job[i-1].endtime<job[j].starttime进行判断,如果不满足就跳过本轮循环。

(3)问题:输出格式保留两位,最后若为0,依旧会被输出

解决方法:班上同学建议将%2f改为%2g

4.扩充了哪些功能(选写)、系统的特色

没有扩充其他的功能。

系统特色:代码简单易懂,运行速度快,运行界面简洁明了,容易快速获得结果。

第三题:

1题目分析(标题均为小三号,宋体黑色加粗)

(正文均为五号,宋体黑色,单倍行距,算法的描述、流程图)

1.题目:

假定某进程共有7页,且系统为之分配了三个物理块,假设已有三个被访问的页面,是:1、2、3,并有以下页面调度序列∶1,2,4,2,6,2,1,5,6,1。

使用以下置换算法:最佳置换算法(OPT)、先进先出置换算法(FIFO)、运用栈结构的最近最少用置换算法(LRU)。

计算并输出:页面置换情况和缺页率。

2.算法描述:

(1)OPT算法描述:

最佳置换算法是由 Belady 于 1966年提出的一种理论上的算法。其所选择的被淘汰页面将是以后永不使用的,或许是在最长(未来)时间内不再被访问的页面。采用最佳置换算法通常可保证获得最低的缺页率。但由于人们目前还无法预知,一个进程在内存的若干个页面中,哪一个页面是未来最长时间内不再被访问的,因而该算法是无法实现的,但可以利用该算法去评价其它算法。

(2)FIFO算法描述:

FIFO 算法是最早出现的置换算法。该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。该算法实现简单,只需把一个进程已调入内存的页面按先后次序链接成一个队列,并设置一个指针,称为替换指针,使它总是指向最老的页面。但该算法与进程实际运行的规律不相适应,因为在进程中,有些页面经常被访问,比如,含有全局变量、常用函数、例程等的页面,FIFO算法并不能保证这些页面不被淘汰。

(3)LRU算法描述:

最近最久未使用(LRU)的页面置换算法是根据页面调入内存后的使用情况做出决策的。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t。当需淘汰一个页面时,选择现有页面中其t值最大的,即最近最久未使用的页面予以淘汰。

3.流程图:

(1)OPT算法流程图:

 

(2)FIFO算法流程图:

 

(3)LRU算法流程图:

 

2系统总体设计

  1. 数据结构设计:即怎么表示数据,用数组存储数据,未使用数据结构体

(1)OPT算法:

该算法使用数组表示和存储数据,没有使用结构体。

(2)FIFO算法:

该算法使用数组表示和存储数据,没有使用结构体。

(3)LRU算法:

该算法使用数组表示和存储数据,没有使用结构体。

  1. 要求列出所有编写的函数清单,说明每个函数的功能,各形式参数的意义

//初始化队列

void initializeList(int list[], int number)

//展示队列状态

void showList(int list[], int number)

//缺页率展示

void informationCount(int missingCount, int pageNum,int chose)

//最佳置换算法,初始化物理块,寻找物理块中最久未被使用的页面,将其与新来的页面进行调换。直接运行即可

void OPT()

//先进先出置换算法FIFO:int memoryList[]内存队列, int phyNum,物理块数 int strList[]引用串, int pageNum页面数,int chose用于选择输出格式

void FIFO(int memoryList[], int phyNum, int strList[], int pageNum,int chose)

//最近最久未使用置换算法:int memoryList[]内存队列, int phyNum,物理块数 int strList[]引用串, int pageNum页面数,int chose用于选择输出格式

void LRU(int memoryList[], int phyNum, int strList[], int pageNum,int chose) {

//主函数

int main()

  1. 系统界面设计:给出操作界面并说明

由数字选择算法可重复选择及退出代码运行输出缺页率和页面序列,在缺页的页面后面输出“×”。

 

3系统详细设计及实现

   写出主函数和每个子函数的实现代码。主函数和子函数必须有注释。

#include <stdio.h>
#include<conio.h>

//初始化队列
void initializeList(int list[], int number)
{
	int date[3]={1,2,3};
	//假设已有三个被访问的页面,是:1、2、3 
    for (int i = 0; i < number; i++)
    {
        list[i] = date[i];
    }
    printf("\n"); 
}
//展示队列状态
void showList(int list[], int number)
{
    for (int i = 0; i < number; i++)
    {
        printf("%2d", list[i]);
    }
    printf("\n");           
}

//缺页率展示 
void informationCount(int missingCount, int pageNum,int chose)
{
	printf("\n");
    printf("***********结果展示***********\n");
    switch (chose)
        {
        case 1:
        	printf("OPT:\n");
            break;
        case 2:
			printf("FIFO:\n");
            break;
        case 3:
         	printf("LRU:\n");
            break;
        default:
            break;
        }
    float date = (float)(missingCount)/(float)(pageNum); 
    printf("缺页率:f = %.2f\n", date);

}
void OPT()
{
	//加载到内存的页面初始为123 
	int loaded[3] = {1,2,3};
	//进度运行所需的页面
	int sequence[99] = {1,2,4,2,6,2,1,5,6,1,-1};
	int pageloss[99] = {0,0,0,0,0,0,0,0,0,0,-1};
	//进程页数、物理块个数
	int useof[3];
	//定义布尔值用以记录 
	bool exist[7] = {0,0,0,0,0,0,0};	
	int pageswapped = 0;
	//缺页次数
	int timeofswap = 0,timeofcalls = 0; 
	
	double page_loss_rate = 0.0;
	
	for(int n=0;n<99,sequence[n]!=-1;n++)
	{
		timeofcalls++;
		for(int m=0;m<3;m++)
		{
			useof[m] = 0;
		}
		if(sequence[n]!=-1)
		{
			for(int m=0;m<3;m++)
			{
				if(sequence[n] == loaded[m])
				{
					exist[n] = 1;
				}
			}
			if(!exist[n])//EXIST[N]=0时 
			{
				timeofswap++;
				//OPT函数开始 
				for(int m=0;m<3;m++)
				{
					for(int N=n;N<99,sequence[N]!=-1;N++)
					{
						if(sequence[N] == loaded[m])
						useof[m]++;
					}
				}
			//当前页面还没访问过
            //内存已满且当前访问不在内存中->进行置换
            //1.寻找到最晚才被访问到的页面 
				int leastused = *useof,theindex = -1;
				for(int m=0;m<3;m++)
				{
					if(useof[m] < leastused)
					{
						leastused = useof[m];
						theindex = m;
					}
				}
				//2.替换最少使用的页面
				pageswapped = loaded[theindex];
				loaded[theindex] = sequence[n];
				pageloss[n] = 1;
			}
		}
	}

	informationCount(timeofswap,timeofcalls,1);
	for(int n=0;n<99,sequence[n]!=-1;n++)
	{
		if(!pageloss[n])
		printf("%d, ",sequence[n]);
		else
		printf("%dx, ",sequence[n]);
	}
}
//先进先出置换算法FIFO
void FIFO(int memoryList[], int phyNum, int strList[], int pageNum,int chose) 
{

    //缺页次数
    int missingCount = 0;
    //记录当前最早进入内存的下标
    int pointer = 0;
    //记录当前页面的访问情况: 0 未访问
    int isVisited = 0;
	int arr[10]={0};
    for (int i = 0; i < pageNum; i++) 
	{
        isVisited = 0;
		
        //判断是否需要置换->内存已满且需要访问的页面不在内存中
        for (int j = 0; j < phyNum; j++) 
		{
            if (memoryList[j] == strList[i]) 
			{
                //该页面已经存在内存中
                //修改访问情况
                isVisited = 1;
                //修改访问时间
                break;
            }
            if (memoryList[j] == -1) 
			{
                //页面不在内存中且内存未满->直接存入
                memoryList[j] = strList[i];
                //修改访问情况
                isVisited = 1;
                missingCount++;
                arr[i]=1;
                break;
            }
            
        }

        if (!isVisited) //isvisited=0未访问 
		{
            //当前页面还未被访问过->需要进行页面置换
            //直接把这个页面存到所记录的下标中
            memoryList[pointer] = strList[i];

            //下标指向下一个
            pointer++;

            //如果到了最后一个,将下标归零
            if (pointer > phyNum - 1) 
			{
                pointer = 0;
            }

			arr[i]=1;
            missingCount++;
            

        }
        
    }
    //结果展示 
    informationCount(missingCount, pageNum,chose);
    
    for(int i=0;i<pageNum;i++)
    {
    	if(arr[i]==0)
    	{
    		printf("%d ", strList[i]);
            if(i<pageNum-1)
				{
					printf(", ");
				}
    	}
    	if(arr[i]==1)
		{
			printf("%dx ", strList[i]);
            if(i<pageNum-1)
				{
					printf(", ");
				}
		}
	}
}
//最近最久未使用置换算法
void LRU(int memoryList[], int phyNum, int strList[], int pageNum,int chose) {


    //缺页次数
    int missingCount = 0;

    //记录内存中最近一次访问至今的时间
    int timeRecord[10];
    //初始化
    initializeList(timeRecord, phyNum);

    //记录当前页面的访问情况: 0 未访问
    int isVisited = 0;

    //记录已经在内存中的页面数量
    int pageCount = 0;
    
    //记录无需缺页中断位置
	int arr[10] = {0}; 
	
    for (int i = 0; i < pageNum; i++) {
        isVisited = 0;

        //时间加一
        for (int p = 0; p < pageCount; p++) {
            if (memoryList[p] != -1) {
                timeRecord[p] ++;
            }
        }

        //是否需要置换
        for (int j = 0; j < phyNum; j++) {
            if (memoryList[j] != -1) {
                timeRecord[j] ++;
            }
            if (memoryList[j] == strList[i]) {
                //该页面已经存在内存中
                //修改访问情况
                isVisited = 1;
                //重置访问时间
                timeRecord[j] = -1;

                break;
            }
            if (memoryList[j] == -1) {
                //页面不在内存中且内存未满->直接存入
                memoryList[j] = strList[i];
                pageCount++;
                //修改访问情况
                isVisited = 1;
                //修改访问时间
                timeRecord[j] ++;

                missingCount++;

                break;
            }
        }

        if (!isVisited) {
            //需要置换
            //1.遍历时间记录表,寻找最久未访问的页面所在的内存下标
            int max = 0;
            for (int k = 0; k < phyNum; k++) {
                if (timeRecord[max] < timeRecord[k]) {
                    max = k;
                }
            }

            //2.将该位置的页面换出
            memoryList[max] = strList[i];
            timeRecord[max] = -1;

            missingCount++;
            
            arr[i]=1;
            

        }
    }
    //结果展示 
    informationCount(missingCount, pageNum,chose);
    //结果展示 
    for(int i=0;i<pageNum;i++)
    {
    	if(arr[i]==0)
    	{
    		printf("%d ", strList[i]);
            if(i<pageNum-1)
				{
					printf(", ");
				}
    	}
    	if(arr[i]==1)
		{
			printf("%dx ", strList[i]);
            if(i<pageNum-1)
				{
					printf(", ");
				}
		}
	}   
}
//主函数 
int main() 
{
	//物理块的数量
	int phyBlockNum = 3;
	//页面数量
	int pageNum =10;
	//保存页面号引用串
	int pageNumStrList[10]= {1,2,4,2,6,2,1,5,6,1};
    //生成内存队列	
	int memoryList[10]={1,2,3};
    printf("***********************************\n");
    printf("*           页面调度算法          *\n");
    printf("***********************************\n");
    //初始化内存状态
    initializeList(memoryList, phyBlockNum);
    printf("*******************************\n");
    printf("调度序列:");
    showList(pageNumStrList, pageNum);
   
    int chose;
    while (1)
    {	printf("*******************************\n");
        printf("选择算法(1.OPT 2.FIFO 3.LRU  0.退出):\n");
        scanf("%d", &chose);
        switch (chose)
        {
        case 1:
        	//OPT
        	OPT();
            initializeList(memoryList, phyBlockNum);            
            break;
        case 2:
            FIFO(memoryList, phyBlockNum, pageNumStrList, pageNum,chose);
            //重新初始化内存
            initializeList(memoryList, phyBlockNum);
            break;
        case 3:
        	//LRU
        	LRU(memoryList, phyBlockNum, pageNumStrList, pageNum,chose);
            //重新初始化内存
            initializeList(memoryList, phyBlockNum);            
            break;
        default:
            return 0;
            break;
        }
    }
    return 0;
}

4运行测试

   (运行效果截图,要针对程序处理的不同情况列出有代表性的输入和输出,用足够多的实例说明程序完成了设计任务和目标。)

 设计测试数据,并输入,给出运行结果

 

5总结

主要说明:

  1. 已经完成了哪些基本要求,完成情况;

完成了OPT算法,FIFC算法和LRU算法,实现了全部基本要求,实现了题目要求的输出。

  1. 未完成哪些基本要求,说明原因;

无基本要求未完成

  1. 遇到了哪些困难,怎么解决;

Opt算法数据计算错误,已修改

  1. 扩充了哪些功能(选写)、系统的特色

集成了三种算法并拥有简单明了的ui设计

系统的特色:代码简单易懂,运行速度快,运行界面简洁明了,容易获得结果。

第四题:

1题目分析(标题均为小三号,宋体黑色加粗)

(正文均为五号,宋体黑色,单倍行距,算法的描述、流程图)

模拟实现移臂调度算法,根据所给数据,计算指定算法的访问顺序和平均寻道长度:

现在读写磁头正在53号柱面上执行输入/输出操作,上一个访问柱面为27。而访问者请求访问的柱面顺序为∶98,183,37,122,14,124,65,67。

须计算的移臂调度算法包括:先来先服务算法(FCFS)、最短寻道时间优先算法(SSTF)、电梯调度算法。

2.算法描述:

(1)FCFS算法描述:

它根据进程请求访问磁盘的先后次序进行调度。

移臂效果图:

 

(2)SSTF算法描述:

该算法选择这样的进程,其要求访问的磁道与当前磁头所在的磁道距离最近,以使每次的寻道时间最短,但这种算法不能保证平均寻道时间最短。

移臂效果图:

 

(3)电梯调度算法描述:

扫描(SCAN)算法不仅考虑到欲访问的磁道与当前磁道间的距离,更优先考虑的是磁头当前的移动方向。例如,当磁头正在自里向外移动时,SCAN算法所考虑的下一个访问对象应是其欲访问的磁道既在当前磁道之外,又是距离最近的。这样自里向外地访问,直至再无更外的磁道需要访问时,才将磁臂换向为自外向里移动。这时,同样也是每次选择这样的进程来调度:即要访问的磁道在当前位置内为距离最近者,这样,磁头又逐步地从外向里移动,直至再无更里面的磁道要访问,从而避免了出现了“饥饿”现象。由于在这种算法中磁头移动的规律颇似电梯的运行,因而又称之为电梯调度算法

移臂效果图:

 

3.流程图:

(1)FCFS流程图:

 

(2)SSTF算法流程图:

 

(3)电梯调度算法流程图:

 

2系统总体设计

  1. 数据结构设计:即怎么表示数据,用数组存储数据,未使用数据结构体

(1)FCFS算法:

创建名为Road的结构体,包含两个与节点有关的变量,通过调用该结构体的各个变量来实现表示数据和存储数据。使用数组存储数据。

typedef struct road{

    int point;     //定义节点的值

    int indicator;    //定义标志符,1为已访问,0为未访问

}Road;    //定义名称为roads的结构体,包含以上两个变量

(2)SSTF算法:

创建名为Road的结构体,包含两个与节点有关的变量,通过调用该结构体的各个变量来实现表示数据和存储数据。使用数组存储数据。

typedef struct road{

    int point;     //定义节点的值

    int indicator;    //定义标志符,1为已访问,0为未访问

}Road;    //定义名称为roads的结构体,包含以上两个变量

(3)电梯调度算法:

创建名为Road的结构体,包含两个与节点有关的变量,通过调用该结构体的各个变量来实现表示数据和存储数据。使用数组存储数据。

typedef struct road{

    int point;     //定义节点的值

    int indicator;    //定义标志符,1为已访问,0为未访问

}Road;    //定义名称为roads的结构体,包含以上两个变量

  1. 要求列出所有编写的函数清单,说明每个函数的功能,各形式参数的意义

(1)FCFS算法:

void FCFS(Road require[], int* first, int allroad); //FCFS算法,按节点顺序进行先来先访问,并统计访问移动的总柱面。require包括节点的值和访问情况的结构体,first是初始化指针,以及之后指向磁头的当前位置,allroad磁头移动的总磁道数。

void init(Road require[], int RequireRoads[],int *first); //初始化节点数组和磁头位置。。require包括节点的值和访问情况的结构体,RequireRoads 是指节点序列,first是初始化指针,以及之后指向磁头的当前位置。

int main():主函数调用其他函数,实现题目要求

(2)SSTF算法:

void SSTF(Road require[], int* first, int allroad);//SSTF算法,先循环找到与当前柱面距离最近的柱面,记录与其之间的距离,再将指针移到该柱面上。require包括节点的值和访问情况的结构体,first是初始化指针,以及之后指向磁头的当前位置,allroad磁头移动的总磁道数。

void SSTF2(Road require[], int* first);//SSTF算法,循环找到与当前柱面距离最近的柱面,将指针移到该柱面上,并输出其值。require包括节点的值和访问情况的结构体,first是初始化指针,以及之后指向磁头的当前位置。

void init(Road require[], int RequireRoads[],int *first);   //初始化节点数组和磁头位置。require包括节点的值和访问情况的结构体,RequireRoads 是指节点序列,first是初始化指针,以及之后指向磁头的当前位置。

int main():主函数调用其他函数,实现题目要求

  1. 电梯调度算法:

//电梯调度算法

Road require[]包括节点的值和访问情况的结构体, int* first是初始化指针,以及之后指向磁头的当前位置, int allroad磁头移动的总磁道数, int before是指初始前一次磁头的位置

void DT(Road require[], int* first, int allroad, int before);

//电梯调度算法,沿一定的方向移动磁头直到到达最边缘的一个节点 ,然后改变方向移动磁头,访问该方向上未访问的节点,直到到达最边缘的节点,依次输出磁头到达的节点。Road require[]包括节点的值和访问情况的结构体,int* first是初始化指针,以及之后指向磁头的当前位置,int before是指初始前一次磁头的位置。

void DT2(Road require[], int* first, int before);

//初始化节点数组和磁头位置。

Road require[]包括节点的值和访问情况的结构体, int RequireRoads[],是指节点序列,first是初始化指针,以及之后指向磁头的当前位置。

void init(Road require[], int RequireRoads[],int *first);

int main():主函数

  1. 系统界面设计:给出操作界面并说明

编译运行输出磁盘移动总柱面和磁盘移动顺序。

 

3系统详细设计及实现

   写出主函数和每个子函数的实现代码。主函数和子函数必须有注释。

(1)

#include<stdio.h>
#include<stdlib.h>
typedef struct road{
    int point;     //定义节点的值 
    int indicator;    //定义标志符,1为已访问,0为未访问 
}Road;    //定义名称为roads的结构体,包含以上两个变量 


void init(Road require[], int RequireRoads[],int *first){ //初始化节点数组和磁头位置
	int i;
    for(i=0;i<9;i++) {
        require[i].point = RequireRoads[i]; 
        require[i].indicator = 0;//标志未被访问 
    }
    int First= 53;
    *first = First;
}
void FCFS(Road require[],int* first,int allroad)
{ //FCFS算法,按节点顺序进行先来先访问,并统计访问移动的总柱面 
    int record=0;
    int i;
    for(i=1;i<9;i++) 
	{
        record = abs(require[i].point - *first)+record; //记录移动的总柱面 
        require[i].indicator = 1;
        *first = require[i].point; //指针移到下一节点 
    }
    allroad = record;
    printf("FCFS:磁盘移动了%d个柱面\n",allroad);
    printf("移动顺序是:");
    for(i=0;i<9;i++) 
	{
        printf("%d", require[i].point);
        if(i<8)
		{
        	printf(", ");
		}
    }
}
int main(){
    int first = 53; //标志磁头初始位位置 
    int RequireRoads[9] = {53,98,183,37,122,14,124,65,67}; //节点值和访问顺序 
    Road require[9]; 
    int allroad; //记录移动的柱面总数 
    init(require, RequireRoads,&first);
FCFS(require,&first,allroad);
return 0;
  }

(2)

#include<stdio.h>
#include<stdlib.h>
typedef struct road 
{
    int point;  //定义节点的值 
    int indicator;  //定义标志符,1为已访问,0为未访问 
}Road;  //定义名称为road的结构体,包含以上两个变量 

void init(Road require[], int requireRoads[],int *first)
{//初始化节点数组和磁头位置
	int i; 
    for(i = 0;i < 9;i++) 
	{
        require[i].point = requireRoads[i]; //赋值 
        require[i].indicator = 0;  //标志未被访问
    }
    int First =53;   //标志指针的初始位置 
    *first = First ;
}
void SSTF(Road require[], int* first, int allroad) 
{//SSTF算法,先循环找到与当前柱面距离最近的柱面,记录与其之间的距离,再将指针移到该柱面上
	int i,j,a;
    int miniRoad = 0, currentRoad = 0, k = 0;//k用来记录是否是第一次访问到未读的磁道
    for(i=0;i<9;i++)
	{//寻找离当前磁头最短位置
        for(j=0;j<9;j++)
		{
            if(k==0&&require[j].indicator==0)
			{//找到未访问第一个时
                miniRoad = abs(require[j].point - *first);//记录柱面之间的磁道个数 
                k=1;
            }
            else if(require[j].indicator==0&&miniRoad>abs(require[j].point-*first))
			{//如果下一个柱面与指针指向的柱面之间的磁道数少于miniRoad所记录的值则修改miniRoad的值 
                	miniRoad = abs(require[j].point - *first);
                }
        }
        k = 0;
        //磁针移动到当前最小位置,并且服务
       for(a=0;a<9;a++)
	   {
            if(abs(require[a].point-*first)==miniRoad&&require[a].indicator==0){
                *first = require[a].point;//移动指针到与原本指针所在柱面之间磁道数等于miniRoad的柱面上 
                require[a].indicator = 1;//将访问记录设为1 
                currentRoad = currentRoad + miniRoad;//累加柱面之间的磁道数 
                break;//找到了满足上述条件的柱面就结束循环 
            }
    	} 
    }
    allroad = currentRoad;
    printf("SSTF:磁盘移动了%d个柱面\n", allroad);
    
}
void SSTF2(Road require[], int* first)
{//SSTF算法,循环找到与当前柱面距离最近的柱面,将指针移到该柱面上,并输出其值 
	int i,j,a;
    int miniRoad = 0,k = 0; //k用来记录是否是第一次访问到未读的磁道
    printf("移动顺序是:");
    for(i=0;i<9;i++)
	{ //寻找离当前磁头最短位置
        for(j=0;j<9;j++)
		{
            if(k==0&&require[j].indicator==0)
			{ //找到未访问第一个时
                miniRoad = abs(require[j].point - *first);//记录柱面之间的磁道个数
                k=1;
            }
            else if(require[j].indicator==0&&miniRoad>abs(require[j].point - *first))
			{
                	miniRoad = abs(require[j].point - *first);//如果下一个柱面与指针指向的柱面之间的磁道数少于miniRoad所记录的值则修改miniRoad的值 
            }
        }
        k = 0;
        //磁针移动到当前最小位置,并且服务
        for(a=0;a<9;a++) 
		{
            if(abs(require[a].point - *first) == miniRoad &&require[a].indicator==0)
			{
                *first = require[a].point;//移动指针到与原本指针所在柱面之间磁道数等于miniRoad的柱面上 
                require[a].indicator = 1;//将访问记录设为1 
                printf("%d", require[a].point);
                if(i<9&&require[a].point!=183)
				{
                	printf(", ");
				}
                break;//找到了满足上述条件的柱面就结束循环 
            }
        }   
    }
}
int main(){
    int first = 53;   //标志磁头初始位位置 
    int RequireRoads[9] = { 53,98,183,37,122,14,124,65,67 };   //节点值和访问顺序 
    Road require[9];
    int allroad;  //记录移动的柱面总数 
    init(require, RequireRoads,&first);
    SSTF(require, &first, allroad);
    init(require, RequireRoads,&first);
SSTF2(require, &first);
return 0;
}

(3)

#include<stdio.h>
#include<stdlib.h>
typedef struct road 
{
    int point;  //节点的值 
    int indicator; //标志是否被访问,“1”表示以访问,“0”表示未被访问 
}Road;//定义包含有节点的值和访问情况的结构体 

void init(Road require[], int requireRoads[],int *first)
{//初始化节点数组和磁头位置
	int i;
    for(i=0;i<9;i++)
	{
        require[i].point = requireRoads[i];//赋值 
        require[i].indicator = 0;//标志未被访问
    }
    int First = 53;
    *first = First;
}
void DT(Road require[],int *first,int allroad,int before)
{//电梯调度算法,沿一定的方向移动磁头直到到达最边缘的一个节点 ,
//然后改变方向移动磁头,访问该方向上未访问的节点,直到到达最边缘的节点,记录总路径 
    int t,x=0;  //t为暂时存储数据的变量 
	int currentRoad=0;
    int breakPoint=0;//记录扫描方向的索引
    int i,j;
    if(before>=*first)
	{
    	x=1; 
	}
    for(i=0;i<8;i++)
	{//排序,使之从小到大排列
        for(j=8;j>i;j--)
		{
            if(require[j].point <require[j - 1].point)
			{
                       t =require[j].point;
                      require[j].point =require[j - 1].point;
                      require[j - 1].point = t;
            }
        }     
    }
    if(x==0)
	{
	    for(i=0;i<9;i++)
		{//找到开始的索引
	        if(require[i].point>=*first)
			{
	            breakPoint=i;
	            break;
	        }
	    }
	    for(i=breakPoint;i<9;i++)//从该点向上扫描
		{
	    	currentRoad = abs(require[i].point - *first) + currentRoad;
	        require[i].indicator = 1;
	        *first =require[i].point;
	    }
	    for(i=breakPoint-1;i>=0;i--)//磁头到达最高点,从该点向下扫描未访问节点 
		{
	    	currentRoad = abs(require[i].point - *first) + currentRoad;
	        require[i].indicator = 1;
	        *first =require[i].point;
	    }
	}
	else if(x==1)
	{
		for(i=0;i<9;i++)//找到开始的索引
		{
	        if(require[i].point<*first)
			{//找小于指针所指节点的最大节点 
	            breakPoint=i;
	        }
	    }
	    for(i=breakPoint+1;i>=0;i--)
		{//磁头从该点向下扫描
	    	currentRoad = abs(require[i].point - *first) + currentRoad;
	        require[i].indicator = 1;
	        *first =require[i].point;
	    }
	    for(i=breakPoint+2;i<9;i++)
		{//磁头到达最低点,从该点向上扫描为访问节点 
	    	currentRoad = abs(require[i].point - *first) + currentRoad;
	        require[i].indicator = 1;
	        *first =require[i].point;
	    }
	}
    allroad = currentRoad;
    printf("电梯调度算法:磁盘移动了%d个柱面\n", allroad);
}
void DT2(Road require[],int *first,int before)
{//电梯调度算法,沿一定的方向移动磁头直到到达最边缘的一个节点 ,然后改变方向移动磁头,访问该方向上未访问的节点,直到到达最边缘的节点,依次输出磁头到达的节点
	int t,x=0;
    int breakPoint=0;//记录扫描方向的索引
    int i,j;
    if(before>=*first)
	{
    	
    	x=1; 
	}
    for(i=0;i<8;i++)
	{//排序,使之从小到大排列
        for(j=8;j>i;j--)
		{
            if(require[j].point <require[j - 1].point)
			{
                       t =require[j].point;
                      require[j].point =require[j - 1].point;
                      require[j - 1].point = t;
            }
        }     
    }
    printf("移动顺序是:"); 
    if(x==0){
	    for(i=0;i<9;i++){//找到开始的索引
	        if(require[i].point>=*first){
	            breakPoint=i;
	            break;
	        }
	    }
	    for(i=breakPoint;i<9;i++){//从该点向上扫描
	    	printf("%d, ",require[i].point);
	        require[i].indicator = 1;
	        *first =require[i].point;
	    }
	    for(i=breakPoint-1;i>=0;i--){//磁头到达最高点,从该点向下扫描未被访问的节点 
	    	printf("%d",require[i].point);
	    	if(i!=0){
	    		printf(", ");
			} 
	        require[i].indicator = 1;
	        *first =require[i].point;
	    }
	}
	else if(x==1)
	{
		for(i=0;i<9;i++)
		{//找到开始的索引
	        if(require[i].point<*first)
			{//找小于指针所指节点的最大节点
	            breakPoint=i;
	        }
	    }
	    for(i=breakPoint+1;i>=0;i--)
		{//从该点向下扫描
	    	printf("%d, ",require[i].point);
	        require[i].indicator = 1;
	        *first =require[i].point;
	    }
	    for(i=breakPoint+2;i<9;i++)
		{//到达最低点,从该点向上扫描未被访问的节点 
	    	printf("%d",require[i].point);
	    	if(i<8)
			{
				printf(", "); 
			}
	        require[i].indicator = 1;
	        *first =require[i].point;
	    }
	}
}

int main()
{
	int before=27;//指针的上一个位置 
    int first=53;//指针初始所在磁道数
    int RequireRoads[9]={53,98,183,37,122,14,124,65,67};
    Road require[9];
    int allroad;
	init(require, RequireRoads,&first);
	DT(require, &first, allroad,before);
    init(require, RequireRoads,&first);
	DT2(require, &first,before);
return 0;
}

4运行测试

   (运行效果截图,要针对程序处理的不同情况列出有代表性的输入和输出,用足够多的实例说明程序完成了设计任务和目标。)

 设计测试数据,并输入,给出运行结果

(1)FCFS

(2)SSTF

(3)电梯调度算法

5总结

主要说明:

1.已经完成了哪些基本要求,完成情况;

完成了FCFS算法,SSTF算法和电梯调度算法,实现所有基本要求,实现题目要求的输出格式。

2.未完成哪些基本要求,说明原因;

(1)问题:对指针的相关知识以及使用不够熟练,在设置指针和对指针进行移动上一直出现错误

解决方法:上网查找了相关知识,借鉴他们对指针的使用方式将其套用,多次尝试,直到显示编译成功。

(2)问题:对break和continue的使用方法混淆

解决方法:查阅相关资料,break用于跳出一个循环体或者完全结束一个循环,不仅可以结束其所在的循环,,还可结束其外层循环continue语句的作用是跳过本次循环体中剩下尚未执行的语句,立即进行下一次的循环条件判定,可以理解为只是中止(跳过)本次循环,接着开始下一次循环。

4.扩充了哪些功能(选写)、系统的特色

无扩充其他的功能。

系统的特色:代码简单易懂,运行速度快,运行界面简洁明了,容易获得结果。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值