操作系统进程管理实验

昆明理工大学信息工程与自动化学院学生实验报告

20## 2011   学年  学期

课程名称:操作系统            开课实验室:信自楼444     20## 年  4 月 10  日

实验目的

通过编写进程管理的算法,要求学生掌握整个进程管理的各个环节,进程的数据结构描述,进程的各种状态之间的转换,以及进程的调度算法。以加深对进程的概念及进程调度算法的理解,并且提高链表的应用能力,达到提高编程能力的目的。

二、实验原理及基本技术路线图(方框原理图)

用C语言或C++语言开发。需要定义PCB的数据结构,用链表的形式管理进程,采用多级反馈队列调度的算法模拟进程的控制。要求有创建、撤销、调度、阻塞、唤醒进程等功能。

进程的状态转换图

数据结构定义、主要变量的说明、函数的说明及各原语的功能说明

typedef struct PCB  定义结构体PCB进程控制块;char NAME[20] 定义结构体变量,进程名;long ID 定义进程id;int RUNTIME 定义进程运行时间;char STATE[6] 定义进程状态 有 ready 、wait 、run;int PRIORITY定义权值。  typedef struct QNode { PCB  pcb; struct QNode *next; }QueuePtr; 定义单链表,有定义指针next。typedef struct LinkQueue { int prior;  QueuePtr *front;  QueuePtr *rear;  int PartTime; }LinkQueue;

链队列中定:优先级、结构体里的QueuePtr类型指针变量,指向该优先级的进程的头结点和尾结点,还运行的时间片。LinkQueue Readyqueue[10] 链队列的单链表。

void schedule() 声明调度函数,用来调度进程的运行;void show() 声明输出函数,用来输出的一个函数;void Create()声明创建进程的函数,用来创建进程。

yunxingshijian=1+(int)(rand()%30); 此语句是随机生成一个整数赋给运行时间RUNTIME;youxianji=1+(int)(rand()%9); 该语句随机生成一个整数(1~9)赋给优先级; strcpy(p->pcb.NAME,name)将名字赋给PCB块;strcpy(p->pcb.STATE,"Ready")将进程状态赋给PCB块; p->pcb.PRIORITY=youxianji将优先级赋给PCB块; p->pcb.RUNTIME=yunxingshijian; 将运行时间赋给PCB块; p->pcb.ID=id 将id号赋给PCB块。

{Readyqueue[i].front->next=p->next; Readyqueue[i+1].rear->next=p;      Readyqueue[i+1].rear=p;   p->next=NULL; } p移到下一队列的队尾,使Readyqueue[i+1].rear指向最后一个结点。{Readyqueue[i].front->next=p->next; Readyqueue[9].rear->next=p; p->next=NULL; Readyqueue[9].rear=p; } //p->next前移,把p移到运行结束的队列Readyqueue[9].rear。

   

多级反馈队列调度算法的描述

一个进程被调度,则其运行时间有p->pcb.RUNTIME=p->pcb.RUNTIME-(int )pow(2,i+1),此后如果该进程的p->pcb.RUNTIME<0或p->pcb.RUNTIME=0,此进程就结束且加入到Readyqueue[9].rear->next=p且p->next=NULL。没有结束就移加到下一队列的尾部且优先级减“1”(Readyqueue[i].front->next=p->next;Readyqueue[i+1].rear->next=p;Readyqueue[i+1].rear=p;p->next=NULL; )。然后往下执行。如此循环.iv Readyqueue[i].front->next!=NULL发生时,就往下一优先级运行。直到所有进程结束。

    

程序功能结构图、流程图

 <1>创建进程函数Create()(左图)                  <2>调度函数schedule()(右图)

三、所用仪器、材料(设备名称、型号、规格等)。

所用仪器:计算中心201;操作系统:Microsoft Visual C++;软件平台:Microsoft Visual C++

四、实验方法、步骤

#include<stdio.h>

#include<malloc.h>

#include<time.h>

#include<math.h>

#include<windows.h>

typedef struct PCB           //定义结构体PCB进程控制块

{

    char NAME[20];           //结构体变量,进程名

    long ID;                 //进程id

    int RUNTIME;             //进程运行时间

    char STATE[6];           //进程状态 ready  wait  run

    int PRIORITY;            //权值 

}PCB;

typedef struct QNode      //单链表

{   PCB  pcb;

    struct QNode *next;

}QueuePtr;

typedef struct LinkQueue      //链队列

{   int prior;                //优先级

    QueuePtr *front;          //结构体里的QueuePtr类型指针变量,指向该优先级的进程的头结点

    QueuePtr *rear;           //结构体里的QueuePtr类型指针变量,指向该优先级的进程的尾结点

    int PartTime;             //时间片

}LinkQueue;

LinkQueue Readyqueue[10];       //链队列的单链表

int N;                          //N为当前进程数

void schedule();                //声明调度函数

void show();                    //声明输出函数

void InitQueue()             //   队列的初始化、给每个队列加个头结点

{

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

    {   

         Readyqueue[i].PartTime=(int )pow(2,i+1);     //每个进程的时间片

         Readyqueue[i].prior=9-i;                     //每进程的优先级

         Readyqueue[i].front=(QueuePtr*)malloc(sizeof(QueuePtr));    //为进程申请空间

         Readyqueue[i].rear=Readyqueue[i].front;      //初始化单链的头结点和尾结点指向同一位置

         Readyqueue[i].front->next=NULL;              //初始化时Readyqueue[i].front->next为空

    }

 }

//***************************创建进程**************************************************

                       

void Create()

    InitQueue();

    char name[20];  long id=201031101;       //定义ID和初始化为201031101

    int m;   

    QueuePtr *p;

    int yunxingshijian,youxianji;            //运行时间、优先级 

    printf("\n\t\t请输入要创建进程的数目:");

    fflush(stdin);

    scanf("%d",&m);

    for(int j=1;j<=m;j++)                    //创建用户所需进程m个

    {   

         printf("\t\t输入进程名:");           //用户输入用户名

         scanf("%s",&name);

              

        srand((int)time(0));        

         yunxingshijian=1+(int)(rand()%30);         //随机生成一个整数赋给运行时间

         printf("\t\t运行时间:%d",yunxingshijian);

       

    srand((int)time(0));    

         youxianji=1+(int)(rand()%9);               //随机生成一个整数(1~9)赋给优先级

         printf("\t优先级:%d",youxianji);

                               

         p=(QueuePtr *)malloc(sizeof(QueuePtr));    //插入就绪队列       

         QueuePtr *k;

         for(int i=0;i<9;i++)                       //通过优先级寻找该进程应放置的队列

         {

              if(youxianji==9-i)

              {

                  k=Readyqueue[i].front;             //k为移动指针,寻找队列末尾进程                                  

                  strcpy(p->pcb.NAME,name);          //将名字赋给PCB块

                  strcpy(p->pcb.STATE,"Ready");      //将进程状态赋给PCB块

                  p->pcb.PRIORITY=youxianji;         //将优先级赋给PCB块

                  p->pcb.RUNTIME=yunxingshijian;     //将运行时间赋给PCB块

                  p->pcb.ID=id;                      //将id号赋给PCB块

                  if(k->next!=NULL)

                  {

                       k=k->next;                     //k指针在寻找队列末尾进程

                  }

                  k->next=p;                         //将p接到队尾

                  p->next=NULL;                      //将队尾的next置为空 

                  Readyqueue[i].rear=p;

              }                 

         }

          N++;                                      //保存当前就绪进程数

          id++;                                     //ID自动加"1"

         printf("\n\t第%d个进程创建成功!\n\n",N);

    }   

         show();                                    //调用输出函数show()

}

//******************************调度函数*******************************************

                             

void schedule()

{

    QueuePtr *p;

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

    {

         while(Readyqueue[i].front->next!=NULL)

         {

              p=Readyqueue[i].front->next;                   //p指向Readyqueue[i].front->next的结点

              Sleep((int )pow(2,i+1));                         //调用函数Sleep()使进程i休眠

              p->pcb.RUNTIME=p->pcb.RUNTIME-(int )pow(2,i+1);  //进程的时间减pow(2,i+1)

              strcpy(p->pcb.STATE,"run");                   //调用strcpy()把状态run复给p->pcb.STATE

                  p->pcb.PRIORITY--;                           //权值减减                                 

                  show();

                  if(p->pcb.RUNTIME<0||p->pcb.RUNTIME==0)      //判断p->pcb.RUNTIME是否<0或=0

                  {

                            Readyqueue[i].front->next=p->next;   //p前移

                            Readyqueue[9].rear->next=p;   //把p移到运行结束的队列Readyqueue[9].rear

                      p->next=NULL;

                          Readyqueue[9].rear=p;            //使Readyqueue[9].rear指向最后一个结点                 

                      strcpy(p->pcb.STATE,"finish");    //调用strcpy()把状态finish复给p->pcb.STATE

                      show();                               //调用输出函数    show()                

                  }

                  else

                  {

                      Readyqueue[i].front->next=p->next;

                      Readyqueue[i+1].rear->next=p;             //p移到下一队列的队尾

                  Readyqueue[i+1].rear=p;                  //使Readyqueue[i+1].rear指向最后一个结点

                       p->next=NULL;         

                       strcpy(p->pcb.STATE,"ready");      //调用strcpy()把状态ready复给p->pcb.STATE

                  }

         }

    }

}

//*******************************输出函数********************************************

void show()                 // 队列输出函数

{  

    QueuePtr  *q=NULL;

    printf("\t名字       ID       运行时间  优先级    状态\n");

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

    {   

         q=Readyqueue[j].front->next;

         while(q!=NULL)

         {

         printf("\t%s,\t%ld,\t%d,\t%d,\t%s\n",q->pcb.NAME,q->pcb.ID,q->pcb.RUNTIME,q->pcb.PRIORITY,q->pcb.STATE);

              q=q->next ;

         }   

    }   

}

//***************************主函数*********************************************

void main()               

{  

    Create();

    char choice;      

    printf("请选择是否要对以上进程进行调度?(y(Y)或n(N))");

    scanf("%s",&choice);                                   //输入choice

    while(1)

    {

         if(choice=='Y'||choice=='y')                            //判断choice的值                        

         {

              schedule();                                //如果choice的值是Y或y 调度schedule()函数

             printf("\t\t\t所有进程 (%d个) 运行结束!\n",N);

              break;                                              //调度结束、退出程序

         }

         if(choice=='N'||choice=='n')                            //如果choice的值是N或n

              exit(0);                                            //退出程序  

         if(choice!='Y'&&choice!='y'&&choice!='N'&&choice!='n') //如果choice的值不是Y或或N或n

         {

              printf("\t\t\t您的选择有误,请重新输入!\n");        //输出出错、重新输入

              scanf("%s",&choice);

         }

    }

}

请加上程序的源代码,需要有详细的注释。

五、实验过程原始记录(数据、图表、计算等)

创建6个进程

进行调度(输入Y或y)

要不调度(输入N或n)

如果输入不是Y或y或N或n,则有如下

在④的情况下,想调度输入Y或y,退出输入N或n即可

程序的测试数据、运行截图

六、实验结果、分析和结论(误差分析与数据处理、成果总结等。其中,绘制曲线图时必须用计算纸)

对整个上机过程、上机结果进行总结、分析。包括收获、存在问题、改进等方面。

在这次上机中,我发现了自己有很多不足。所以花了很长的时间才做出来,而且还在 

老师多次的讲解之后,才悟出来的。真是有点惭愧了。

      在编程的过程中,就没有明白数组队列、链队列、PCB块及结构体的真正意思。所以

老师说了是半懂不懂的,虽说从图书馆借来一本类似的书看,可到用时还是不完全明白。在这几天,我努力了,我敢说。就连睡觉了我都会在想为什么不可以这样、那样,看了好多学过的和没学过的书、知识点。用多级反馈队列来实现,虽说没有很多美化的功能,我

相信,只要好好学,下一次我会做得好。此外,存在的问题还是不少的,比如好多学过的知识都不记得了,也许是好长时间没复习了,也可能是太久没编程序了。不过这也是我自己的问题所在。真心的说,遇到杨老师这样的好老师,我很欣慰。有耐心、讲得仔细、重

复的讲重点、举例说明难点、讲课精神足等等,真是当今大学难有的好老师。

     在这次有深度的上机,觉得这样的程序还可以改进,比如:程序运行背景、算法的简

洁等等。我突然觉醒:我该努力了

相关推荐