1.实验题目:模拟进程调度功能
2.实验目的:通过本实验,进一步掌握进程调度的功能和实现原理。
3.实验环境:
(1)硬件:pc 机。
(2)软件:Windows OS,Visual C++ 6.0(完整绿色版)
4.程序清单:
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#define LEN sizeof(Pnode)
typedef struct Pnode
{
char pname[30];//进程名
int status;//状态0:就绪,1:执行,2:阻塞
int runtime;//运行时间
int prior;//优先级
struct Pnode *next;//指针
}Pnode, *PCB;
void fprior(PCB ready,PCB run){
PCB pn = run;
PCB py = ready,py2 = ready->next,p = ready->next, p1;
int n = 0;
if(py->next == NULL)
printf(“run empty!\n”);
else{
//删除run队列中的结点
while (py2){
if(py2->prior > p->prior)
p = py2;
py2 = py2->next;
}//end while
//从ready队列中选择优先权最高的进程(假设为p进程)
while(py->next != p){
py = py->next;
}//end while
p1 = p->next;
py->next = p1;
//将p进程从就绪队列中删除;
while(pn->next)
{pn = pn->next;}
pn->next = p;
pn->next->status = 1;
printf("%s \n",p->pname);
//将p进程插入到run队列中
}
}
void ftimeschedule(PCB ready,PCB run,int ts){
PCB py = ready, py1 = ready , pn = run , p , p1;
if(py->next == NULL)
printf(“ready is empty”);
else{
pn->next = NULL;
py = ready;
p = py->next;
p1 = p->next;
py->next = p1;//从就绪队列中拿下第一个结点p
p->status = 1;//将结点p的状态修改为1
p->next =NULL;
pn->next = p;//将结点插入run队列中
p->runtime = p->runtime - ts;//将结点p的运行时间减去一个时间片
printf("结点名称为: %s",p->pname); printf(" 运行剩余时间为:%d\n",p->runtime);//显示结点p的名称以及剩余时间
if(p->runtime > 0){
pn->next = NULL;
while(py1->next){
py1 = py1->next;
printf(py1->pname);
}
py1->next = p;
p->status = 0;
}//endif
else{
pn->next = NULL;
}//若剩余时间>0,将结点p从run队列中拿下,修改状态后放入就绪队列的尾部,否则从run队列中删除该结点
printf("you can continue\n");
}
}
void frun(PCB ready, PCB run, int method){
int flag = 1;
while(flag == 1){
switch(method){
case 1: fprior(ready,run); break;
case 2:
int ts;
printf(“please input a timeslice”);
scanf("%d",&ts);//输入系统设定的时间片
ftimeschedule(ready,run,ts); break;
}
printf(“Do you want to run another one 1:yes 0:no :”);
scanf("%d",&flag);
}
}
/create函数:用于将新建的PCB插入就绪队列中/
void fcreate(PCB ready, PCB run, PCB block, int method)
{
PCB p = NULL;
PCB py = ready;
PCB pn = run;
PCB pk = block;
char name[30];
int flag = 1;
while (flag == 1)
{
printf(“please input pname:”);
scanf("%s",name);
//输入新建进程的名称pname;
//在ready、run、block三个队列中查找是否重名
while (py->next)
{
py = py->next;
if (strcmp(py->pname, name) == 0) {
printf(“please input pname again”);
scanf("%s", name);
}
}
while (pn->next)
{
pn = pn->next;
if (strcmp(pn->pname, name) == 0) {
printf("please input pname again");
scanf("%s", name);
}
}
while (pk->next)
{
pk = pk->next;
if (strcmp(pk->pname, name) == 0) {
printf("please input pname again");
scanf("%s", name);
}
}
p = (PCB)malloc(LEN);/*申请空白PCB: */
/*初始化该PCB:输入该进程的相关信息*/
strcpy(p->pname,name);//Q:strcpy是什么 A:将p的名字复制给pname
printf("prior: "); scanf("%d", &p->prior);
printf("runtime: "); scanf("%d", &p->runtime);
p->status = 0;
p->next = NULL;
py->next = p;// 将该节点p插入ready队列;
printf("Do you want to create anthoer one(1:yes 0:no):");
scanf("%d", &flag);
}
}
/block函数:用于阻塞正在执行的进程,阻塞后会引起新的进程调度/
void fblock(PCB ready,PCB run,PCB block, int method)
{
PCB pk = block;
PCB pn = run;
PCB p,t;
if(pn->next){
p = pn->next;//从run队列中找到当前正在执行进程的PCB
t = p->next;
pn->next = t;//将该PCB从run队列中取出
p->status = 2;//将其状态修改为2
while(pk->next)
{pk = pk->next;}//让新PCB插入最后队伍
pk->next = p;//将该PCB插入到block队列中
printf(pk->next->pname);
printf(“已阻塞\n”);
frun(ready,run,method);//从ready队列中选择新的进程执行(调用frun函数即可)
}
else
printf(“无可阻塞的进程\n”);
}
/wakeup函数:用于唤醒阻塞队列中的进程,将其插入到就绪队列中/
void fwakeup(PCB ready,PCB run, PCB block, int method)
{
int flag = 1;
PCB pk2 = block->next;
PCB py = ready;
PCB pn = run;
PCB pk = block;
PCB p;
char pname[30];
while(flag==1)
{
printf(“please input the pname you want to wake up:”);
scanf("%s",pname);//输入要唤醒进程的名称pname
while(pk2)
{
if(strcmp(pk2->pname,pname) == 0){//在block队列中查找是否存在
pk2->status=0; /*将状态修改为0*/
p = pk2->next;
pk->next = p;
//将该节点从block队列中取下
while(py->next){
py = py->next;
}
py->next = pk2;
//将该节点插入ready队列中;
printf("已唤醒");
if(pn->next == NULL)//如果run队列为空
frun(ready,run,method);// 调用frun函数;
break;
}//end if
else if(pk2->next){
pk2 = pk2->next;
pk = pk->next;
}
else
printf("the block link is null");//end else 提示“阻塞队列中没有进程”
}//end whilepk2
printf("Do you want to wakeup anthoer one(1:yes 0:no):");
scanf("%d",&flag);
}//end whileflag
}//end wakeup
/delete函数:用于撤销进程/
void fdelete(PCB ready,PCB run, PCB block, int method)
{
int flag = 1;
char name[30];
PCB py = ready,py2 = ready->next;
PCB pn = run,pn2 = run->next;
PCB pk = block,pk2 = block->next;
PCB p = NULL;
while(flag == 1)
{
printf("please input the pname you want to delete");
scanf("%s",name);//输入要撤销进程的名称pname;
//在ready、run、block三个队列中查找是否重名
while (py2)
{
if (strcmp(py2->pname, name) == 0) {
p = py2->next;
py->next = p;
printf("ready中的进程已撤销\n");
break;
}
py = py->next;
py2 = py2->next;
}
while (pn2)
{
if (strcmp(pn2->pname, name) == 0){
p = pn2->next;
pn->next = p;
printf("run中的进程已撤销\n");
break;
}
pn = pn->next;
pn2 = pn2->next;
}
while (pk2)
{
if (strcmp(pk2->pname, name) == 0){
p = pk2->next;
pk->next = p;
printf("block中的进程已撤销\n");
break;
}
pk = pk->next;
pk2 = pk2->next;
}
if(!p)
printf("the pcb don't exist");//提示“内存中没有该进程”
if(!run->next)
frun(ready,run,method);
printf("Do you want to delete another one(1:yes 0:no):");
scanf("%d",&flag);
}
}
/show函数:显示三个队列中的PCB/
void showlist(char str[], PCB p)
{PCB q;
q=p->next;
puts(str);
if(q==NULL) printf(“NULL\n”);
else
while(q)
{printf(q->pname);//输出q结点的内容;
q=q->next;
}
}
void fshow(PCB ready,PCB run,PCB block)
{
showlist(“Ready List:”,ready);
showlist("\n Run List:",run);
showlist("\n Block List:",block);
printf("\n");
}
void fmenu(int method)
{
PCB ready, run, block;//定义三个链表的头指针
int select;//接受用户输入的功能号
int flag = 1;//控制循环的变量
/*初始化ready,run,block为带头结点的空链表*/
ready = (PCB)malloc(LEN);
ready->next = NULL;
run = (PCB)malloc(LEN);
run->next = NULL;
block = (PCB)malloc(LEN);
block->next = NULL;
/*设计整个系统框架*/
while (flag == 1) /*当flag的值等于0时,程序结束*/
{ /*构建系统菜单*/
printf("**********Main Menu************\n");
printf("**********1----create***************\n");
printf("**********2----run***************\n");
printf("**********3----delete***************\n");
printf("**********4----block***************\n");
printf("**********5----wakeup***************\n");
printf("**********6----show***************\n");
printf("**********0----return***************\n");
printf("**************************************\n");
printf(" input your choice(0-5):");
/*接收用户从键盘输入的功能号*/
scanf("%d", &select);
/*函数调用*/
switch (select)
{
case 1: fcreate(ready, run, block, method); break;
case 2: frun(ready, run, method); break;
case 3: fdelete(ready,run,block, method);break;
case 4: fblock(ready,run,block, method);break;
case 5: fwakeup(ready,run,block, method);break;
case 6: fshow(ready,run,block);break;
case 0: flag=0;break;
default: printf("input error!");break;
}/*end switch*/
}/*end while*/
}/*end main*/
void main(){
int flag = 1;
int select;
while(flag == 1){
printf("系统调度算法\n");
printf("1---高优先权优先调度\n");
printf("2---时间片轮转调度\n");
printf("0---退出\n");
printf("请输入选择:");
scanf("%d",&select);
switch(select){
case 1:
case 2: fmenu(select); break;
case 0: flag = 0; break;
default: printf(“input error!\n”); break;
}//end switch
}
}
5.调试程序时出现问题说明及解决的方法