处理机调度模拟(优先权调度算法)

来源:互联网 发布:淘宝店铺退款率高 编辑:程序博客网 时间:2024/04/23 21:23

/*该程序只能在TrobuC2.0环境下运行*/

#include <math.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <graphics.h>
#define ESC 0x1b
#define ENTER 0x0d
#define TRUE 1
#define FALSE 0

typedef struct _pcb { /*进程结构*/
 int PID; /*进程号*/
 long time; /*单位时间为1ms*/
 int priority; /*优先级,最高为0,最低为7*/
 int status; /*0表示就绪,1表示执行*/
 struct _pcb * next;
} PCB;

PCB * ProcQueue = NULL; /*进程队列*/
int TIMESLICE = 20; /*初始化系统时间片为20ms*/
int PROCNUM = 0; /*ProcQueue进程队列元素个数*/

int InsertProc(int prior, long time);/*向进程链表中按优先级大小插入一个新进程*/
int SortProcQueue();/*将进程链表按优先级从大到小排列*/

int InsertProc(int prior, long time)
{
 static int sysid = 0;/*该系统已经加入过多少进程,此值将是新进程的ID*/
 PCB * last, * now, * pcb;
 pcb = (PCB *)malloc(sizeof(PCB));
 if (pcb == NULL)
  return FALSE;
 pcb->PID = (++sysid);
 pcb->priority = prior;
 pcb->time = time;
 pcb->status = 0;
 if (ProcQueue == NULL) { /*如果进程队列为空*/
  ProcQueue = pcb;
  pcb->next = NULL;
  return TRUE;
 }
 if (ProcQueue->status == 0)
  if (pcb->priority < ProcQueue->priority) { /*pcb将排在队头*/
   pcb->next = ProcQueue;
   ProcQueue = pcb;
  return TRUE;
 }
 last = ProcQueue;
 now = last->next;
 while ((now != NULL) && (pcb->priority >= now->priority)) { /*寻找插入位置*/
  last = now;
  now = last->next;
 }
 last->next = pcb;
 pcb->next = now;
 return TRUE;
}

int SortProcQueue()
{
 PCB * pcb = ProcQueue;
 PCB * head, * last, * now;
 last = pcb;
 head = now = pcb->next;
 while ((now != NULL) && (pcb->priority >= now->priority)) {
  last = now;
  now = last->next;
 }
 if (last != pcb) {
  last->next = pcb;
  pcb->next = now;
  ProcQueue = head;
 }
 return TRUE;
}

/****************************************************************/

/*图形界面相关函数*/
/****************************************************************/
/*表格的单位宽度和高度*/
#define WIDTH 64
#define HEIGHT 12
void *black=NULL;/*背景色方格,使用它擦出表格中的图形*/
int InitGraph()/*初始化图形界面*/
{
 int GraphDriver;  /* The Graphics device driver  */
 int GraphMode;  /* The Graphics mode value  */
 int ErrorCode;
 GraphDriver = DETECT;   /* Request auto-detection */
 initgraph(&GraphDriver, &GraphMode, "");
 ErrorCode = graphresult();  /* Read result of initialization*/
 if( ErrorCode != grOk ) {  /* Error occured during init */
  printf(" Graphics System Error: %s/n", grapherrormsg( ErrorCode ) );
  getch();
 return FALSE;
 }
 cleardevice();
 black = (void*)malloc(imagesize(1,1,WIDTH-1,HEIGHT-1));
 getimage(1,1,WIDTH-1,HEIGHT-1,black);
 DrawFrame();
 return TRUE;
}

int DrawFrame()/*画边框和表头*/
{
 settextjustify(CENTER_TEXT, CENTER_TEXT);
 gprintf(320, HEIGHT/2-1, "Processor Dispatch Simulation Emulation");
 settextjustify(LEFT_TEXT, TOP_TEXT);
 moveto(0,HEIGHT);
 lineto(0,419);
 lineto(639,419);
 lineto(639,HEIGHT);
 lineto(0,HEIGHT);
 line(WIDTH*5,HEIGHT,WIDTH*5,419);
 line(0,HEIGHT*2,639,HEIGHT*2);
 line(0,HEIGHT*3,639,HEIGHT*3);
 gprintf(HEIGHT*0+2,HEIGHT*1+2,"Run Processes");/*表头*/
 gprintf(WIDTH*0+2,HEIGHT*2+2,"PID");
 gprintf(WIDTH*1+2,HEIGHT*2+2,"Time");
 gprintf(WIDTH*2+2,HEIGHT*2+2,"priority");
 gprintf(WIDTH*4+2, HEIGHT*2+2, "Status");
 gprintf(WIDTH*5+2,HEIGHT*1+2,"Ready Processes");/*就绪队列列表头*/
 gprintf(WIDTH*5+2,HEIGHT*2+2,"PID");
 gprintf(WIDTH*6+2,HEIGHT*2+2,"Time");
 gprintf(WIDTH*7+2,HEIGHT*2+2,"priority");
 gprintf(WIDTH*9+2, HEIGHT*2+2, "Status");
 gprintf(10, 421, "Press 'i': Insert new process.");
 gprintf(10, 435, "Press 't': Change the timeslice.");
 gprintf(10, 450, "Press 'ESC': Quit.");
 gprintf(10, 465, "Press 'ENTER': Execute.");
 gprintf(330, 421, "Timeslice: %dms", TIMESLICE);
}

int DlgGetNum(char *buf,int l,int t,int r,int b,int flag) /*输入数字*/
{
 char ch;
 int pos=0;
 bar(l,t,r,b);
 switch (flag) {
 case 0:
  gprintf(l+10,t+5,"Add new Process");
  gprintf(l+10,t+20,"input the time:");
  break;
 case 1:
  gprintf(l+10,t+5,"Change the timeslice");
  gprintf(l+10,t+20,"input new timeslice:");
  break;
 }
 while (1) {
  ch = getch();
  if (ch == ENTER) { /*如果输入了回车键*/
   if(pos!=0) { /*如果位置不在第一位(回车键不准第一个输入)*/
    buf[pos]='/0';
    break;
   }
  }
  else if (ch>='0' && ch<='9') {
   buf[pos++]=ch;
   buf[pos]='/0';
  }
  else if (ch == ESC) {
   return FALSE;
  }
  else { /*其他按键均按BackSpace处理*/
   --pos;
   buf[pos]='/0';
  }
  if (pos<0) {
   pos=0; buf[pos]='/0';
  }
  else if (pos>5) { /*最多输入4位数*/
   pos=5; buf[pos]='/0';
  }
  bar(l,t+35,r,t+47);
  gprintf(l+50,t+35,buf);
 }
 return TRUE;
}

int NewProc() /*新建进程*/
{
 int l=200,t=150,r=380,b=200,pos=0,prior=0;
 long time=0;
 char buf[6],ch;
 PCB * pcb;
 void * bg = (void*)malloc(imagesize(l,t,r,b));
 getimage(l,t,r,b,bg);
 setfillstyle(1,2);
 flushall();
 prior = abs((rand()+clock())) % 8;
 /*******输入时间**********/
 pos=0;
 buf[pos]='/0';
 if (!DlgGetNum(buf,l,t,r,b,0))
  goto exit;
 time = atoi(buf);
 InsertProc(prior, time);
 PROCNUM++;
exit:
 putimage(l,t,bg,COPY_PUT);
 free(bg);
 return TRUE;
}

int Timeslice() /*修改系统时间片*/
{
 int l=200,t=150,r=380,b=200,pos=0;
 char buf[6],ch;
 void * bg = (void*)malloc(imagesize(l,t,r,b));
 getimage(l,t,r,b,bg);
 setfillstyle(1,2);
 flushall();
 pos=0;
 buf[pos]='/0';
 if (!DlgGetNum(buf,l,t,r,b,1))
  goto exit;
 TIMESLICE = atoi(buf);
exit:
 putimage(l,t,bg,COPY_PUT);
 free(bg);
 return TRUE;
}

int gprintf( int xloc, int yloc, char *fmt, ... )/*图形系统中的格式输出*/
{
 va_list argptr;   /* Argument list pointer */
 char str[140];   /* Buffer to build sting into */
 int cnt;    /* Result of SPRINTF for return */
 va_start( argptr, format );  /* Initialize va_ functions */
 cnt = vsprintf( str, fmt, argptr ); /* prints string to buffer */
 outtextxy( xloc, yloc, str ); /* Send string in graphics mode */
 va_end( argptr );   /* Close va_ functions  */
 return( cnt );   /* Return the conversion count */
}

int DrawData()/*绘制系统数据*/
{
 int numRun=0, numRed=0;/*运行挂起和就绪的进程各有多少*/
 PCB* now = ProcQueue;
 int x=0, y=0;
 while (now != NULL) {
  switch(now->status) {
  case 1:
   x = WIDTH*0;
   y = HEIGHT*(3+(numRun++));
  break;
  case 0:
   x = WIDTH*5;
   y = HEIGHT*(3+(numRed++));
  break;
  }
  putimage(x+1,y+1,black,COPY_PUT);
  gprintf(x+2,y+2,"%d",now->PID);
  putimage(x+WIDTH,y+1,black,COPY_PUT);
  gprintf(x+WIDTH+2,y+2,"%ld",now->time);
  putimage(x+WIDTH*2,y+1,black,COPY_PUT);
  gprintf(x+WIDTH*2+2,y+2,"%d",now->priority);
  putimage(x+WIDTH*4,y+1,black,COPY_PUT);
  if (now->status == 0)
   gprintf(x+WIDTH*4+2,y+2,"READY");
  else
   gprintf(x+WIDTH*4+2,y+2,"RUN");
  now = now->next;
 }
}

int DrawError(int flag) /*提示错误*/
{
 int l=200,t=150,r=380,b=200;
 void * bg = (void*)malloc(imagesize(l,t,r,b));
 getimage(l,t,r,b,bg);
 setfillstyle(1,2);
 flushall();
 bar(l,t,r,b);
 switch (flag) {
 case 0:
  gprintf(l+10,t+5,"ProcQueue is NULL!");
  gprintf(l+10,t+20,"Press any key to");
  gprintf(l+10,t+35,"continue!");
  break;
 }
 getch();
 cleardevice();
 DrawFrame();
}

int main()
{
 char kb;
 int flag = 2;
 PCB * temp = NULL;

 InitGraph();
 while (1) {
  kb = getch();
  switch (kb) {
  case ESC:
   closegraph();
   return 0;
  case ENTER:
   switch (flag) {
   case 0: /*从就绪到运行*/
    ProcQueue->status = 1;
    ProcQueue->time -= TIMESLICE;
    if (ProcQueue->time < 0)
     ProcQueue->time = 0;
    cleardevice();
    DrawFrame();
    DrawData();
    flag = 1;
    break;
   case 1: /*从运行到就绪*/
    ProcQueue->status = 0;
    if (ProcQueue->priority <= 6)
     ProcQueue->priority += 1;
    if (ProcQueue->time <= 0) {
     temp = ProcQueue;
     ProcQueue = ProcQueue->next;
     free(temp);
     if (--PROCNUM == 0) {
      flag = 2;
      cleardevice();
      DrawFrame();
      break;
     }
    }
    cleardevice();
    DrawFrame();
    SortProcQueue();
    DrawData();
    flag = 0;
    break;
   case 2: /*ProcQueue为空*/
    DrawError(0);
    break;
   }
   break;
  case 'i': /*插入新进程*/
   NewProc();
   cleardevice();
   DrawFrame();
   if (PROCNUM > 0) {
    if (flag == 2)
     flag = 0;
    DrawData();
   }
   break;
  case 't': /*修改时间片*/
   Timeslice();
   cleardevice();
   DrawFrame();
   DrawData();
   break;
  }
 };
}