#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef struct node{
char name;//进程标识符
int prio;//进程优先级数
int round;//进程时间片轮转时间片
int cputime;//进程占用cpu时间
int needtime;//进程完成还需要的时间
int count;//计数器
char state;//进程状态
struct node *next;//链指针
}PCB;
PCB *ready,*running,*finish;
PCB *CreatNode()
{
PCB *head;
head=(PCB *)malloc(sizeof(PCB));
head->next=NULL;
return head;
}
//进程动态优先数算法
void InsertPrio(PCB *process)//把生成的节点进行优先级插入
{
PCB *tmp;
tmp=ready;
while(tmp->next!=NULL&&process->prio <=tmp->next->prio )
{
tmp=tmp->next;
}
process->next=tmp->next;
tmp->next=process;
}
void PrioCreate(int num)//创建轮转优先级队列(就绪队列)
{
PCB *tmp;
int i;
printf("进程名\t优先级\t所需时间:\n");
for(int i=0;i<num;i++)
{
getchar();
tmp=(PCB *)malloc(sizeof(PCB));
char Name;
scanf("%c",&Name);
tmp->name=Name;
int pri;
scanf("%d",&pri);
tmp->prio=pri;
int ntime;
scanf("%d",&ntime);
tmp->needtime=ntime;
tmp->state='W';
InsertPrio(tmp);
}
}
void ReadyToRun()//把就绪队列的第一个节点 (优先级最高) 变成运行态,插入running队列
{
PCB *tmp;
if(ready->next!=NULL)
{
tmp=ready->next;
ready->next=tmp->next;
tmp->next=running->next;
running->next=tmp;
running->next->state='R';
}
}
OutPutPrio()//对每次的运行情况进行打印
{
PCB *tmp;
printf("进程\t优先级\t所需时间\t状态\n");
tmp=ready->next;
while(tmp!=NULL)
{
printf("%c\t%d\t%d\t\t%c\n",tmp->name,tmp->prio,tmp->needtime,tmp->state);
tmp=tmp->next;
}
PCB *t;
t=running->next;
while(t!=NULL)
{
printf("%c\t%d\t%d\t\t%c\n",t->name,t->prio,t->needtime,t->state);
t=t->next;
}
PCB *p;
p=finish->next;
while(p!=NULL)
{
printf("%c\t%d\t%d\t\t%c\n",p->name,p->prio,p->needtime,p->state);
p=p->next;
}
}
void InsertReady(PCB *process)//运行一次之后(该进程的needtime!=0),重新插入就绪队列
{
PCB *tmp;
tmp=ready;
while(tmp->next!=NULL&&process->prio <=tmp->next->prio )
{
tmp=tmp->next;
}
process->state='W';
process->next=tmp->next;
tmp->next=process;
}
void InsertFinish(PCB* process)//运行一次之后(该进程的needtime==0) ,插入完成队列
{
PCB *tmp;
tmp=finish;
while(tmp->next!=NULL)
{
tmp=tmp->next;
}
process->state='F';
process->next=tmp->next;
tmp->next=process;
}
void PrioRun()
{
PCB *tmp;
while(true)
{
ReadyToRun();
OutPutPrio();
if(running->next==NULL)break;
running->next->prio-=3;
running->next->needtime-=1;
if(running->next->needtime==0)
{
tmp=running->next;
running->next=tmp->next;
InsertFinish(tmp);
}
else
{
tmp=running->next;
running->next=tmp->next;
InsertReady(tmp);
}
}
}
//轮转
void InsertRound(PCB *process)
{
PCB *tmp;
tmp=ready;
while(tmp->next!=NULL&&process->prio <=tmp->next->prio )
{
tmp=tmp->next;
}
process->next=tmp->next;
tmp->next=process;
}
void RoundCreate(int num)
{
PCB *tmp;
int i;
printf("进程名\t优先级\t所需时间\t轮转时间片数:\n");
for(int i=0;i<num;i++)
{
getchar();
tmp=(PCB *)malloc(sizeof(PCB));
char Name;
scanf("%c",&Name);
tmp->name=Name;
int pri;
scanf("%d",&pri);
tmp->prio=pri;
int ntime;
scanf("%d",&ntime);
tmp->needtime=ntime;
tmp->state='W';
tmp->count=tmp->needtime;//记录初始时间,needtime为负数时,将这个值给cputime
int round;
scanf("%d",&round);//每个进程都有自己的时间片
tmp->round=round;
InsertRound(tmp);
tmp->cputime=0;
}
}
OutPutRound()
{
PCB *tmp;
printf("进程\t优先级\t所需时间\t轮转时间片数\t状态\t已占用CPU时间片数\n");
tmp=ready->next;
while(tmp!=NULL)
{
printf("%c\t%d\t%d\t %d\t\t%c\t%d\n",tmp->name,tmp->prio,tmp->needtime,tmp->round,tmp->state,tmp->cputime);
tmp=tmp->next;
}
PCB *t;
t=running->next;
while(t!=NULL)
{
printf("%c\t%d\t%d\t %d\t\t%c\t%d\n",t->name,t->prio,t->needtime,t->round,t->state,t->cputime);
t=t->next;
}
PCB *p;
p=finish->next;
while(p!=NULL)
{
printf("%c\t%d\t%d\t %d\t\t%c\t%d\n",p->name,p->prio,p->needtime,p->round,p->state,p->cputime);
p=p->next;
}
}
void RoundRun()
{
PCB *tmp;
while(true)
{
ReadyToRun();
OutPutRound();
if(running->next==NULL)break;
running->next->prio-=3;
running->next->needtime-=running->next->round;
running->next->cputime+=running->next->round ;
if(running->next->needtime<=0)
{
running->next->needtime=0;
running->next->cputime=running->next->count;
tmp=running->next;
running->next=tmp->next;
InsertFinish(tmp);
}
else
{
tmp=running->next;
running->next=tmp->next;
InsertReady(tmp);
}
}
}
int main()
{
int num;
ready=CreatNode();
running=CreatNode();
finish=CreatNode();
printf("进程数:\n");
scanf("%d",&num);
getchar();
printf("调度算法的选择(Y/N,Y优先权法,N时间片轮转)\n");
char choose;
scanf("%c",&choose);
switch(choose)
{
case 'Y':
PrioCreate(num);
PrioRun();
break;
case 'N':
RoundCreate(num);
RoundRun();
break;
}
return 0;
}
1)使用优先数调度算法完成进程的调度
1) 采用动态优先数法确定进程的优先级别。
2) 设计三个链队列,分别用来表示运行队列、就绪队列和完成队列。
3) 用户输入进程标识符以及进程所需要的时间,申请空间存放进程 PCB 信息。
优先数调度算法为每个进程设一个优先数,它总是把处理机分配给就绪队列中具有最高优先权
的进程。常用的算法有静态优先数法和动态优先数法。
动态优先数法使进程的优先权随时间而改变。初始的进程优先数取决于进程运行所需要的时
间,时间长则优先数低。可采取将进程优先数定为一个较大的数(比如 50)减去进程运行所需要
的时间。
随着进程的运行对优先数进行调整,每次运行时都是从就绪队列中选取优先数最大的进程运
行。以一个时间片为固定周期 T,每个周期动态调整各个进程的优先级,当前正在执行的进程优先
级降低(优先数减小),所有就绪进程优先级提升(优先数增加),每个时间片开始时,重新选择当
前优先级最高的进程投入运行。如果进程所需时间为 0,说明进程运行完毕,将其状态变为完成状
态“
F”,将此进程 PCB 插入到完成队列中。重复上述过程,直到就绪队列为空,所有进程都变为
完成状态为止。
(
2)使用时间片轮转算法完成进程的调度
时间片轮转调度:具体做法是调度程序每次把 CPU 分配给当前最高优先级进程使用一个时间
片。当这个时间片结束时,强迫该进程让出处理器,进行下一轮优先级调度,直至就绪队列中所有
进程都运行完成为止。实现这种调度要使用一个间隔时钟。当一个进程开始运行时,就将时间片的
值置入间隔时钟内,当发生间隔时钟中断时,就表明该进程连续运行的时间已超过一个规定的时间
片。此时,中断处理程序就通知处理器调度进行处理器的切换工作。