实验一: 进程状态转换及PCB的模拟

本文介绍了一个基于最高优先数优先调度算法的进程调度模拟实验。实验实现了进程创建、优先级排序、进程运行、撤销等基本功能,并通过具体代码展示了实验全过程。
实验目的

1)加深对进程概念的理解。
2)深入了解进程控制块和进程状态之间的转换。
3)掌握进程调度算法。

实验预备知识

1)进程的状态


2)进程的结构——PCB

进程都是由一系列操作(动作)所组成,通过这些操作来完成其任务。因此,不同的进程,其内部操作也不相同。在操作系统中,描述一个进程除了需要程序和私有数据之外,最主要的是需要一个与动态过程相联系的数据结构,该数据结构用来描述进程的外部特性(名字、状态等)以及与其它进程的联系(通信关系)等信息,该数据结构称为进程控制块(PCB,Process Control Block)。

进程控制块PCB与进程一一对应,PCB中记录了系统所需的全部信息、用于描述进程情况所需的全部信息和控制进程运行所需的全部信息。因此,系统可以通过进程的PCB来对进程进行管理。

实验步骤

1)设计一个有 N个进程共行的进程调度程序。

2)进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)。每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间。进程的运行时间以时间片为单位进行计算。每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或阻塞F(Finish)三种状态之一。就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。  

3)重复以上过程,直到所要进程都完成为止。

调度算法的流程图如下 :


实验结论

1)给出实验源程序(附有详细注释)

2)程序运行截图

#include <stdio.h>
#include <stdlib.h>

typedef struct pcb
{
	int name; // 进程的名称
	char state;// 进程的状态
	int arrivetime; //进程的到达时间
	int runtime;// 进程的执行时间
	int cputime;//cpu占用的时间
	int count;//优先数
	struct pcb *next;
}pcb;
pcb *head = NULL; // 正常对列
pcb *head1 = NULL; // 未到达的对列
int n = 0;// 进程的数量
//创建头指针
void createhead()
{
	pcb *p = (pcb*)malloc(sizeof(pcb));// 创建头指针
	head = p;
	pcb *q = (pcb*)malloc(sizeof(pcb));// 创建头指针
	head1 = q;
}
void sort()// 按照优先数进行排序
{
	pcb* t = head;
    pcb *q,*p,*r;
    int max;
    while(t->next != NULL)
    {
		p = t->next;
		r = t->next;
		max = r->count;
        while(r!= NULL)
        {
			if(r->count > max)
			{
				max = r->count;
                p = r;
			}
            r = r->next;
		}// p指向count最大的那一个数
        q = t;
		while (q->next != p)
			q = q->next;
		if(t->next != p)
		{
			q->next = p->next;
			p->next = t->next;
			t->next = p;
		}// 插入进行排序按照优先数
        t = t->next;
	}
}
bool create() //创建pcb操作
{
	createhead();
	pcb *p = head;
	pcb *q = head1;
	printf("请输入进程数目:");
	scanf("%d",&n);
	pcb *temp;
    for(int i=1;i<=n;i++ )//尾插法建立就绪队列
    {
		temp = (pcb*)malloc(sizeof(pcb));
        if(!temp) return false;
        printf("请输入进程%d的要求运行时间,进程优先数,到达时间:",i);
		scanf("%d %d %d",&(temp->runtime),&(temp->count),&(temp->arrivetime));
		temp->cputime = 0;
        temp->name=i;
		temp->next = NULL;
        temp->state='W';
		if(temp->arrivetime!=0) // 对到达时间进行判断
		{
			q->next = temp;
			q = temp;
		}
		else
		{
			p->next = temp;
			p = temp;
		}
	}
	sort(); // 排序
	return true;
}
void destory(pcb *rp)// 撤销操作
{
	printf("****************进程%d已完成****************\n",rp->name);
	pcb *q = rp->next;
	head->next = q;
	free(rp);
}
void display(pcb *rp) // 展示当前的信息
{
	printf("进程名字:%d",rp->name);
	printf("\n进程优先级:%d",rp->count);
	printf("\n进程所占时间片:%d",rp->runtime);
	printf("\n进程已运行时间:%d",rp->cputime);
	printf("\n进程当前状态:%c",rp->state);
	printf("\n=====================================\n");
}
void arrivetime()// 对于到达时间-1的操作
{
	pcb *q = head1->next;
	pcb *r,*t;
	while(q!=NULL) // 判断到达时间是否为0 此时是否到达
	{
		q->arrivetime--;
		if(q->arrivetime==0)
		{
			t = head1;
			while(t->next!=q)
				t = t->next;
			t->next = q->next;
			r = head->next;
			q->next = r;
			head->next = q;
		}
		q = q->next;
	}
}
void runpcb(pcb *rp)
{
	rp->cputime++; //修改cpu占用的时间
	arrivetime();
	printf("----------正在运行的进程----------\n"); // 输出正在运行的队列
	display(rp);
	if(rp->cputime==rp->runtime)
	{
		destory(rp);
	}
	else
	{
		rp->count--;
		rp->state = 'W';
	}
	pcb *p = head;
	if(head->next==NULL&&head1->next==NULL) return;
	printf("----------处于就绪对列的进程----------\n"); // 输出就绪的队列
	while(p->next!=NULL)
	{
		display(p->next);
		p = p->next;
	}
	pcb *q = head1;
	while(q->next!=NULL)
	{
		display(q->next);
		q = q->next;
	}
	sort();
}
int main()
{
	create();// 创造进程
	pcb * p;
	while(head->next!=NULL || head1->next!=NULL) // 判断两个对列的进程是否都走完
	{
		if(head->next!=NULL)
		{
			p= head->next;
			p->state='R';
			runpcb(p);
		}
		else
		{
			arrivetime();
		}
	}
	return 0;
}


1.目的: 自行编制模拟程序,通过形象化的状态显示,深入理解进程的概念、进程之间的状态转换及其所带来的PCB内容 、组织的变化,理解进程与其PCB间的对应关系。 2. 内容及要求: 1) 设计并实现模拟进程状态转换及其相应PCB内容、组织结构变化的程序。 2) 独立编写、调试程序。进程的数目、进程的状态模型(三状态、五状态、七状态或其它)以及PCB的组织形式可自行选择。 3) 合理设计与进程PCB相对应的数据结构。PCB的内容要涵盖进程的基本信息、控制信息、资源需求及现场信息。 4) 设计出可视性较好的界面,应能反映出进程状态的变化引起的对应PCB内容、组织结构的变化。 5) 代码书写要规范,要适当地加入注释。 6) 认真进行预习,完成预习报告。 7) 实验完成后,要认真总结,完成实验报告。 3.使用的数据结构及说明: 在本实验中,主要用到的数据结构是PCB的结构,其中PCB的数据结构如下: struct PCB { int P_Id; //PCB的ID号 char P_Name[10]; //PCB的名称 char P_State[10]; //PCB状态 int P_Runtime; //PCB的所需要的运行时间 int P_Requiry; //PCB所需要的资源要求 struct PCB * next ; //PCB块的下个指针 } ; 其中,P_Id,和P_Name用来标示进程,而P_State用来标示进程的五种状态:Create_state,Ready_state,Block_state,Run_state,Exit_state。P_Runtime标示要完成进程所需要的时间。P_Requiry标示进程的执行所需要的其他条件,当其他的条件满足,则P_Requiry置1,否则置0。Struct PCB * next 用来指向同队列中的下PCB块。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值