进程调度

沈 阳 工 程 学 院

学 生 实 验 报 告

(课程名称:   操作系统  

实验题目:         进程调度                         

班 级           学 号          姓 名                 

地 点  实训F606   指导教师   吕海华  刘娜               

实 验 日 期 :  2015     10     10  



源代码:

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

/********************这是先来先服务的程序*********************************/

struct fcfs{//定义先来先服务结构体、参数

char name[10];

float daodatime;//到达时间

float fuwutime;//服务时间

float kaishitime;//开始时间

float wanchengtime;//完成时间

float zhouztime;//周转时间

float daiquantime;//带权周转时间

};fcfs a[100];

void input(fcfs *p,int N)  //构造一个输入进程的信息的函数,定义结构体指针

{

       int i;  

   for(i=0;i<=N-1;i++)

   {

     printf("输入第%d个进程的名字、到达时间、服务时间:\n",i+1);

     scanf("%s%f%f",&p[i].name,&p[i].daodatime,&p[i].fuwutime);//把输入的信息保存到结构体指针所对应的内存中

   }

}//构造一个输出函数

void Print(fcfs *p,float daodatime,float fuwutime,float kaishitime,float wanchengtime,float zhouztime,float daiquantime,int N)

{

       int k;

    printf("执行顺序:\n");

    printf("%s",p[0].name);

    for(k=1;k<N;k++)

       {

              printf("-->%s",p[k].name);

       }

     printf("\n进程的相关信息如下:\n");

     printf("\n名字\t到达\t服务\t开始\t完成\t周转\t带权周转\n");

     for(k=0;k<=N-1;k++)

        {

      printf("%s\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t%-.2f\t\n",p[k].name,p[k].daodatime,p[k].fuwutime,p[k].kaishitime,p[k].wanchengtime,p[k].zhouztime,p[k].daiquantime);

        } //题目中加入-.2是保留双精度的两位。一般f默认保留六位小数的。 

}

  void sort(fcfs *p,int N)//进程根据到达时间进行排序

  {

     for(int i=0;i<=N-1;i++)

      for(int j=0;j<=i;j++)

       if(p[i].daodatime<p[j].daodatime)//如果i的时间到达时间小于j的到达时间,就交换

          {

         fcfs temp;//在结构体中定义第三个变量进行交换

         temp=p[i];

         p[i]=p[j];

         p[j]=temp;

          }

}

//核心的运行阶段

void deal(fcfs *p, float daodatime,float fuwutime,float kaishitime,float wanchengtime,float zhouztime,float daiquantime,int N)

{ int k;

    for(k=0;k<=N-1;k++)

       {

         if(k==0)//K=0,表示第一个进程到达

         {

       p[k].kaishitime=p[k].daodatime;//那么开始时间=到达时间

       p[k].wanchengtime=p[k].daodatime+p[k].fuwutime;//完成时间=到达时间+服务时间

         }

         else

               {

           p[k].kaishitime=p[k-1].wanchengtime;//下一个进程的开始时间=上一个进程的完成时间

           p[k].wanchengtime=p[k-1].wanchengtime+p[k].fuwutime;//完成时间=上一个进程的完成时间+服务时间

               }

       }

     for(k=0;k<=N-1;k++)//计算周转时间和带权周转时间

     {

      p[k].zhouztime=p[k].wanchengtime-p[k].daodatime;//周转时间=完成时间-到达时间

      p[k].daiquantime=p[k].zhouztime/p[k].fuwutime;//带权周转时间=周转时间/服务时间  

        }

}

void FCFS(fcfs *p,int N)//定义先来先服务函数

     float daodatime=0,fuwutime=0,kaishitime=0,wanchengtime=0,zhouztime=0,daiquantime=0;//初始化变量为0

     sort(p,N);//声明排序函数

     deal(p,daodatime,fuwutime,kaishitime,wanchengtime,zhouztime,daiquantime,N);//声明运行函数

     Print(p,daodatime,fuwutime,kaishitime,wanchengtime,zhouztime,daiquantime,N); //声明输出函数

}

/***********************这是算法时间片轮转法的代码*****************************************/

struct shijian {//定义时间片的结构体

       char name;  //定义进程名

    int daodatime;// 到达时间

    int fuwutime;  //服务时间

    int shengyutime;//剩余时间

       char *state;//所处状态

       struct shijian *next;

};

struct shijian *time()

{

       int a,i;

       struct shijian *head, *rear,*p,*q,*t;//定义队首、队尾、P是队尾指针、Q是队首指针和执行时间

       head=rear=NULL;//初始化队首和队尾为空

    printf("请输入进程数目:"); 

    scanf("%d",&a);

       for(i=0;i<a;i++)

       {

              p=(struct shijian*)malloc(sizeof(struct shijian)); //初始化一个空间给进程进入

              printf("输入第%d个进程的名字、到达时间、服务时间:\n",i+1);

        scanf("%s%d%d",&p->name,&p->daodatime,&p->fuwutime); 

        p->shengyutime=p->fuwutime;

        p->state="就绪";           

        if(rear==NULL) //当输入结束时,把P的数据放到队首,以便执行下一步

              {

                     head=p;  

            p->next=NULL;  

            rear=p; 

              }

              else  //否则执行时间就为空,队首变成Q

              {

                     t=NULL;  

            q=head;

                     while(q&&q->daodatime<p->daodatime)//当Q和Q的到达时间小于P的到达时间时,把执行时间给Q

                     {

                            t=q;     

                q=q->next;

                     }

                     if(q==head)  //而当Q是队首时,则下一个队首变成P,以便每个进程都能够得到时间片

                     {

                            p->next=head; 

                head=p;

                     }

                     else if(t==rear)  //当执行时间片到达队尾时(执行完时),返回给队首P

                     {

                            rear->next=p;

                p->next=NULL;

                rear=p;

                     }

                     else   //否则给队首P占用执行时间,P执行完后到Q

                     {

                            t->next=p;  

                p->next=q;

                     }  

              }  

       }

       return head;//返回队首

}

void output(struct shijian *head)//定义输出函数

{

       struct shijian *p,*t,*r;

    int num; 

    printf("请输入时间片:"); 

    scanf("%d",&num);

       while(head!=NULL) //当队首不为空时,把P给队首

       {

              r=p=head;

              while(p!=NULL) //把执行时间给队首

              {

                     t=head; 

            p->shengyutime=p->shengyutime-num;  //P的剩余时间=剩余时间-时间片

            p->state="运行"; //状态变成运行态

            if(p->shengyutime<0) //当P运行完,即剩余时间小于0时,仍然把它当做0处理

            p->shengyutime=0; 

            printf("\n************程序开始运行*****************\n");

            printf("进程  到达时间 服务时间  剩余时间  当前状态\n");

                     while(t!=NULL)  //时间不为空时,输出当前进程的信息,并把时间片交给下一个进程

                     {

                            printf("%2c%8d%8d%14d%10s\n",t->name,t->daodatime,t->fuwutime,t->shengyutime,t->state); 

                t=t->next;

                     }

                     getchar(); //按住回车键观看

                     if(p->shengyutime==0)//当队首的剩余时间为0时,先把队首改成P的下一个,然后释放内存,删除队首节点

                     {

                            if(p==head)

                            {

                                   head=p->next;

                          free(p);

                          p=head;

                            }

                            else  //否则返回执行,把队尾的下一个指针变成P的下一个指针,队尾的位置移动到队首

                            {

                                   r->next=p->next;

                    p=r->next;

                    r=p;

                            }

                     }

                     else  //否则把队首的位置给队尾,把队首的状态显示为“就绪”状态

                     {

                            r=p;

                            p->state="就绪";   

                p=p->next;

                     }

              }   

    }

/****************************这是优先服务调度算法的代码***********************************/

typedef struct PCB2

   char name[10];//进程名

   int runtime;//要求运行时间

   int frist;//定义优先数

   char zhuangtai; //定义状态,R为就绪,F为完成

};

struct PCB2 PCBcontrol[4];//定义进程控制块数组

void youxian()//构造优先函数

{

       int i,n;

       printf("请输入进程的个数:\n");

    scanf("%d",&n);

       printf("请输入进程的名字、优先权、运行时间\n");

       printf("\n");

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

       {

              printf("请输入第%d个进程的信息:\n",i+1);

              scanf("%s%d%d",&PCBcontrol[i].name,&PCBcontrol[i].frist,&PCBcontrol[i].runtime);

        PCBcontrol[i].zhuangtai='R';//进程初始状态均为就绪

        getchar();//等待回车进入下一次运行

       }

}

  int max_frist_process()//确定最大优先级进程子程序

  {

     int max=-10;//max为最大优先数,初始化为-10 

     int i,key; 

     for(i=0;i<3;i++)

        {

               if(PCBcontrol[i].zhuangtai=='r')//r表示正在运行

                      return -1;//返回-1

               else

                      if(max<PCBcontrol[i].frist&&PCBcontrol[i].zhuangtai=='R')//从就绪进程中选取优先数最大的进程

                      {

                             max=PCBcontrol[i].frist;//max存放每次循环中的最大优先数

                             key=i;//将进程号赋给key

                      }

        }

        if(PCBcontrol[key].zhuangtai=='F')//具有最大优先数的进程若已运行完毕

               return -1;//则返回-1

        else

               return key;//将key作为返回值返回

  }

  void show()//显示函数

  {

         int i; 

      printf("\n进程名  优先级 运行时间 当前状态\n");

         printf("*****************************************\n");

      for(i=0;i<3;i++)//依次显示每个进程的名、优先数、要求运行时间和状态

         {

                printf("  %s\t %d\t  %d\t   %s\t\n",&PCBcontrol[i].name,PCBcontrol[i].frist,PCBcontrol[i].runtime,&PCBcontrol[i].zhuangtai);

         }

          printf("\n请按回车键进行查看");

  }

  void run()//进程运行子程序

  {

         int i,j;

         int t=0;//t为运行次数

         for(j=0;j<3;j++)

         {

                t+=PCBcontrol[j].runtime;}//运行次数即为各个进程运行时间之和

          printf("\n进程没运行前,当前的状态是:\n"); 

          show(); //调用show()子程序显示运行前PCB的情况

                getchar();//等待回车进入下一次运行

                for(j=0;j<t;j++)

                {

                       while(max_frist_process()!=-1)//具有最大优先数的进程没有运行完,让其运行

                       {

                              PCBcontrol[max_frist_process()].zhuangtai='r';//将其状态置为r,表示其正在运行

                       }

                       for(i=0;i<3;i++)

                       {

                              if(PCBcontrol[i].zhuangtai=='r')

                              {

                                     PCBcontrol[i].frist-=1;//将当前运行进程的优先数减1

                                     PCBcontrol[i].runtime--;//要求运行时间减1

                                     {

                                            if(PCBcontrol[i].runtime==0)

                                                   PCBcontrol[i].zhuangtai='F';//运行完则将该进程状态置为结束

                                            else

                                                   PCBcontrol[i].zhuangtai='R';//未运行完将其状态置为就绪

                                     }

                                     show();//显示每次运行后各PCB的情况

                                     getchar();//等待回车进入下一次运行

                              } 

                       }

                }

  }

  void main()

  {

         int N;

         int number;

         char Tishikuang;//提示框

         do{

        printf("***************************************************************************\n");

        printf("***************************************************************************\n");

        printf(" **************************************************************************\n");

       printf("************************  【进程调度算法】 ********************************\n");

       printf("***************************************************************************\n");

        printf("    **                       输入 1—先来先服务                           *\n");

        printf("    **                       输入 2—时间片轮转法                         *\n");

        printf("    **                       输入 3—优先服务法                           *\n");

        printf("    **                       输入 0—退出该程序                           *\n");

        printf("    ***********************************************************************\n");

        printf("\n提示:请根据自己的需求选择相应的操作数:\n");

        scanf("%d",&number);/*提示输入字母,用switch语句存入到case中,最后增加提示框是否继续*/

        switch(number)

        {

        case 0:

           break;

        case 1:

             printf("\n您选择的是“先来先服务项目”\n\n");

                   printf("请输入进程的数量:\n");

             scanf("%d",&N);

             input(a,N);

             FCFS(a,N);

            break;

        case 2:

                     printf("\n您选择的是“时间片轮转法项目”\n\n");

                     struct shijian *head; //定义时间片的队首结构体

            head=time(); //队首执行的时间

            output(head) ;//输出函数

            break;

        case 3:

                     printf("\n您选择的是“优先服务项目”,本程序可提供3个进程的调度。\n\n");

                  youxian();//初始化各个进程PCB

            run();//进程调度模拟

                 break;

        default:

            printf("\n你的输入有误,请确定是从0到3之间进行输入,O(∩_∩)O谢谢\n");

            break;

        }

        printf("\n是否继续操作(y/n) ?");

        fflush(stdin);

        Tishikuang=getchar();

       }while(Tishikuang=='y'||Tishikuang=='Y');

}