zoukankan      html  css  js  c++  java
  • 模拟简单进程调度实验

    一、实验目的及要求
    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信息,每当一个进程完成运行,输出该进程已完成的信息,最后当所有进程都完成后给出所有进程都完成的信息。

  • 相关阅读:
    并发编程(线程)
    并发编程(进程)
    并发编程(操作系统的介绍)
    模块与包
    网络编程
    Django项目的创建与管理和pycharm与Github的秘密
    python解释器配置和python常用快捷键
    代码的调试.运行
    57. 三数之和
    1347. 尾随零
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3052226.html
Copyright © 2011-2022 走看看