模拟简单进程调度实验

一、实验目的及要求
1. 用C语言编写和调试一个模拟进程调度程序,以加深对进程的概念及进程调度算法的理解,模拟过程的数据结构和算法符合主流操作系统的进程调度规则(从第2点开始给出过程规则)。
2. 进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)。
3. 每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程名、优先数、需要运行时间、已用CPU时间、进程状态等等。
4. 进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。
5. 每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。
6. 进程的运行时间以时间片为单位进行计算。
7. 就绪进程获得CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。
8. 采用最高优先数算法的动态优先数法则控制进程:如果运行一个时间片后,进程的已占用CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。
9. 每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。
10. 重复以上过程,直到所要进程都完成为止。

二、实验内容与步骤

1.数据结构
1.1 进程控制块结构PCB:是struct定义的结构体,定义如下:
typedef struct pcb
{
    char qname[20];/*进程名*/
    char state;    /*进程状态*/
    int super;     /*进程优先级*/
    int ndtime;    /*进程需要运行的时间*/
    int runtime;   /*进程已运行的时间*/
    int cpu;       /*进程当前获得的时间片大小*/
}PCB;

1.2  队列结点Node,结点储存PCB信息,定义如下:
typedef struct node
{
    PCB data;              /*结点数据*/
    struct node *next; /*指向下一结点的指针*/
}Node;

1.3 由队列结点Node扩展的队列Queue,定义如下:
typedef struct queue
{
    Node *front;/*队首*/
    Node *rear;/*队尾*/
}Queue;

2.相关函数
2.1 判断一个队列q是否为空的函数int is_empty(Queue *q);
2.2 将进程控制块x加入队列q的函数void enqueue(PCB x,Queue *q);
2.3 删除队列q的队首进程,将其值赋给x并修改状态的函数void dequeue(PCB *x,Queue *q);
   该函数将队列q的队首进程删除,由于可能该进程未运行完毕,需进入下一优先级队列, 所以先修改其结构体内成员变量:已运行时间为上次已运行时间加上这次获得的cpu时间;优先级减1(若该进程已是最低优先级,则将在主控过程中恢复);下次获得的时间片为这次的时间片加1。然后将修改后的进程赋给一个临时PCB变量x,以便将x插入下一优先级队列。
2.4 主函数
   利用上述的数据结构和函数实现模拟进程调度。

3. 进程产生模拟

通过标准输入模拟产生进程:先要求输入进程数目,再依次输入各个进程的进程名、进程优先数、进程需要运行的时间。

三、参考代码

#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<conio.h>
#define PCB_LEN sizeof(PCB)
#define NODE_LEN sizeof(Node)
#define QUEUE_LEN sizeof(Queue)
/*进程控制块结构PCB*/
typedef struct pcb
{
	char qname[20];/*进程名*/
    char state;    /*进程状态*/
	int super;     /*进程优先级*/
	int ndtime;    /*进程需要运行的时间*/
	int runtime;   /*进程已运行的时间*/
	int cpu;       /*进程当前获得的时间片大小*/
}PCB;
/*队列结点,结点储存PCB信息*/
typedef struct node
{
	PCB data;
    struct node *next;
}Node;
/*实现进程控制块的队列*/
typedef struct queue
{
	Node *front;
	Node *rear;
}Queue;
/*判断队列是否为空*/
int is_empty(Queue *q)
{
	if(q->front)
		return 0;
	else
		return 1;
}
/*将进程控制块x加入队列q*/
void enqueue(PCB x,Queue *q)
{
    Node *p=(Node *)malloc(NODE_LEN);
	(p->data).state=x.state;
	(p->data).super=x.super;
	(p->data).ndtime=x.ndtime;
	(p->data).runtime=x.runtime;
	(p->data).cpu=x.cpu;
	strcpy((p->data).qname,x.qname);
	p->next=0;
	if(q->front)
		q->rear->next=p;
	else
		q->front=p;
	q->rear=p;
}
/*删除队列q的队首进程,将其值赋给x并修改状态*/
void dequeue(PCB *x,Queue *q)
{
	Node *p=(Node *)malloc(NODE_LEN);
    if(is_empty(q))
		return;
	/*进入下一优先级队列之前修改状态*/
	x->state='W';/*状态改为就绪*/
	strcpy(x->qname,(q->front->data).qname);
	/*已运行时间为上次已运行时间加上这次获得的cpu时间*/
	x->runtime=(q->front->data).runtime+(q->front->data).cpu;
	/*优先级减1,若该进程已是最低优先级,则将在主控过程中恢复*/
	x->super=(q->front->data).super-1;
	x->ndtime=(q->front->data).ndtime;
	/*下次获得的时间片为这次的时间片加1*/
	x->cpu=(q->front->data).cpu+1;
	p=q->front;
	q->front=q->front->next;
	free(p);
}
/*主控过程*/
void main()
{
	Queue *queue=NULL;/*设置就绪队列数组*/
	Node *wait=(Node *)malloc(NODE_LEN);
	PCB x;
	int numberOFcourse,i,j,super,time;
	int hight=0,num=0;
	int temp_ndtime,temp_runtime,temp_cpu;
	char name[20];
	printf("\n请输入进程总个数?");
	scanf("%d",&numberOFcourse);
	/*为队列数组开辟空间,每个数组表示不同的优先级队列*/
	queue=(Queue *)calloc(numberOFcourse,QUEUE_LEN);
	/*输入各进程信息并初始化,并将其加入相应的优先级队列*/
	for(i=0;i<numberOFcourse;i++)
	{
		printf("\n进程号 NO.%d\n",i);
		printf("\n输入进程名:");
		scanf("%s",name);
		printf("\n输入进程优先数:");
		scanf("%d",&super);
		if(super>hight)
			hight=super;
		printf("\n输入进程运行时间:");
		scanf("%d",&time);
		strcpy(x.qname,name);
		x.state='W';
        x.super=super;
		x.ndtime=time;
		x.runtime=0;
		x.cpu=1;
		enqueue(x,&queue[super-1]);
	}
	printf("\n\n");
	/*进程调度过程*/
	for(i=hight-1;i>=0;i--)
	{
		/*从最高优先级队列开始调度进程,
		直到该队列为空,则调度下一优先级队列*/
		while(!is_empty(&queue[i]))
		{
			num++;/*调度次数*/
			printf("按任一键继续......\n");
			getch();
			printf("The execute number:%d\n\n",num);
			/*打印正在运行进程*/
			((queue[i].front)->data).state='R';
			printf("******当前工作的进程是:%s\n",((queue[i].front)->data).qname);
			printf("qname    state    super    ndtime    runtime\n");
			printf("%s        ",((queue[i].front)->data).qname);
            printf("R         ");
			printf("%d        ",(((queue[i].front)->data).super));
            printf("%d        ",(((queue[i].front)->data).ndtime));
			printf("%d\n\n",(((queue[i].front)->data).runtime));
			/*计算一个进程运行一个时间片后,还需要运行的时间temp_time*/
            temp_ndtime=((queue[i].front)->data).ndtime;
			temp_runtime=((queue[i].front)->data).runtime;
            temp_cpu=((queue[i].front)->data).cpu;
			temp_ndtime=temp_ndtime-temp_runtime-temp_cpu;
			/*若该进程已运行完毕*/
			if(temp_ndtime<=0)
			{
				/*打印已完成信息,并将其删除出队列*/
				printf("进程[%s]已完成\n\n",((queue[i].front)->data).qname);
                ((queue[i].front)->data).state='F';
                dequeue(&x,&queue[i]);
			}
			/*若该进程未运行完毕*/
			else
			{
                dequeue(&x,&queue[i]);/*将其删除出当前队列*/
				/*若原优先级不是最低优先级,则插入下一优先级队列*/
				if(i>0)
					enqueue(x,&queue[i-1]);
				/*若原优先级是最低优先级,则插入当前队列末尾*/
				else
				{
					/*由于删除操作中将优先级减1,所以在此恢复*/
					x.super=x.super+1;
                    enqueue(x,&queue[i]);
				}
			}
			/*打印就绪队列状态*/
            printf("******当前就绪队列状态为:\n");
			for(j=i;j>=0;j--)
			{
				if(queue[j].front)
				{
					wait=queue[j].front;
					while(wait)
					{
						printf("qname    state    super    ndtime    runtime\n");
			            printf("%s        ",(wait->data).qname);
                        printf("W         ");
			            printf("%d        ",(wait->data).super);
                        printf("%d        ",(wait->data).ndtime);
			            printf("%d\n\n",((wait->data).runtime));
                        wait=wait->next;
					}
                }
			}
			printf("\n");
		}
	}
	/*结束*/
	printf("进程已经全部完成\n");
	free(wait);
	free(queue);
	getch();
}


四、实验结果与数据处理

【输入输出样例】

请输入进程总个数?4

进程号 NO.0

输入进程名:aa

输入进程优先数:2

输入进程运行时间:2

进程号 NO.1

输入进程名:vv

输入进程优先数:3

输入进程运行时间:2

进程号 NO.2

输入进程名:rr

输入进程优先数:1

输入进程运行时间:3

进程号 NO.3

输入进程名:kk

输入进程优先数:2

输入进程运行时间:1

按任一键继续......
The execute number:1

******当前工作的进程是:vv
qname    state    super    ndtime    runtime
vv        R         3        2        0

******当前就绪队列状态为:
qname    state    super    ndtime    runtime
aa        W         2        2        0

qname    state    super    ndtime    runtime
kk        W         2        1        0

qname    state    super    ndtime    runtime
vv        W         2        2        1

qname    state    super    ndtime    runtime
rr        W         1        3        0


按任一键继续......
The execute number:2

******当前工作的进程是:aa
qname    state    super    ndtime    runtime
aa        R         2        2        0

******当前就绪队列状态为:
qname    state    super    ndtime    runtime
kk        W         2        1        0

qname    state    super    ndtime    runtime
vv        W         2        2        1

qname    state    super    ndtime    runtime
rr        W         1        3        0

qname    state    super    ndtime    runtime
aa        W         1        2        1


按任一键继续......
The execute number:3

******当前工作的进程是:kk
qname    state    super    ndtime    runtime
kk        R         2        1        0

进程[kk]已完成

******当前就绪队列状态为:
qname    state    super    ndtime    runtime
vv        W         2        2        1

qname    state    super    ndtime    runtime
rr        W         1        3        0

qname    state    super    ndtime    runtime
aa        W         1        2        1


按任一键继续......
The execute number:4

******当前工作的进程是:vv
qname    state    super    ndtime    runtime
vv        R         2        2        1

进程[vv]已完成

******当前就绪队列状态为:
qname    state    super    ndtime    runtime
rr        W         1        3        0

qname    state    super    ndtime    runtime
aa        W         1        2        1


按任一键继续......
The execute number:5

******当前工作的进程是:rr
qname    state    super    ndtime    runtime
rr        R         1        3        0

******当前就绪队列状态为:
qname    state    super    ndtime    runtime
aa        W         1        2        1

qname    state    super    ndtime    runtime
rr        W         1        3        1


按任一键继续......
The execute number:6

******当前工作的进程是:aa
qname    state    super    ndtime    runtime
aa        R         1        2        1

进程[aa]已完成

******当前就绪队列状态为:
qname    state    super    ndtime    runtime
rr        W         1        3        1


按任一键继续......
The execute number:7

******当前工作的进程是:rr
qname    state    super    ndtime    runtime
rr        R         1        3        1

进程[rr]已完成

******当前就绪队列状态为:

进程已经全部完成

 

五、总结

        本程序利用标准输入输出模拟了进程调度过程。输入各个进程的优先级和需要运行的时间等信息,输出给出了每进行一次调度的运行进程、就绪队列、以及各个进程的 PCB信息,每当一个进程完成运行,输出该进程已完成的信息,最后当所有进程都完成后给出所有进程都完成的信息。

 

 

posted @ 2013-04-30 18:09  javawebsoa  Views(626)  Comments(0Edit  收藏  举报