【操作系统实践--进程控制】

一、实验目的

用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解。

二、实验内容

编写进程调度算法:采用基于时间片轮转的最高优先数优先算法(即把处理机分配给优先数最高的进程)。

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

三、编程环境及工具

Dev-C++ 5.11

四、具体设计及有关说明

设计思想:

  1. 通过循环将输入的进程信息存入进程结构体数组中,并初始化结构体数组的值;
  2. 通过循环计算需要循环的总次数;
  3. 开始总次数的循环:①对数组进行排序:根据数组的状态(“F”或“W”)将数组分为数组p1和p2,然后p1根据输入先后顺序排序,p2根据优先级数从高到低排序(若优先级数相同,则根据等待时间从大到小排序),再将p1、p2按顺序赋值给进程结构体数组p;②在p数组从p2赋值过来的数组(即状态为“W”)的第一个数组的队列信息进行数据更新(即将需要运行的第一个进程进行运行);
  4. 循环结束,进程运行结束;

数据结构:

运用了结构体数组,结构体代表进程的信息汇总,结构体数组来表示多个进程;

流程图:

  1. 主流程图:
    在这里插入图片描述
  2. 总次数的循环的流程图:
    在这里插入图片描述

代码:

#include<bits/stdc++.h>
#include<conio.h>
using namespace std;

int N;  //定义总进程数 
struct node		//定义进程结构体 
{
	char name[10];	//进程名
	int ndtime;		//进程要求运行的时间 
	char state;		//进程状态3种,R表示运行状态,W表示就绪状态,F表示完成状态
	int super;		//优先数
	int wait;       //等待时间 
	int runtime;    //已经运行时间 
	int jointime;   //进程输入的时间 
};				
typedef struct node P; //用P替代结构体的类型名 

//排序算法 :根据数组的状态(“F”或“W”)将数组分为数组p1和p2
//然后p1根据输入先后顺序排序,p2根据优先级数从高到低排序(若优先级数相同,则根据等待时间从大到小排序)
//再将p1、p2按顺序赋值给进程结构体数组p 
void Sort(P* p)
{
	//分别定义结构体数组p1、p2 
	P* t= new P[1];
	P* p1 = new P[N+2];
	P* p2 = new P[N+2];
	int p11=0,p22=0;
	//通过循环,将根据数组的状态(“F”或“W”)将数组p分为数组p1和p2 
	for(int i=0;i<N;i++)
	{
		if(p[i].state=='F')
		{
			p1[p11]=p[i];
			p11++;
		}
		else
		{
			p2[p22]=p[i];
			p22++;
		}
	}
	//将p1根据输入先后顺序排序
	for (int i = 0; i < p11-1; i++)
	{ 
		for (int j = 0; j < p11-1 - i; j++)
		{
			if (p1[j].jointime > p1[j + 1].jointime)
			{
				t[0] = p1[j + 1];
				p1[j + 1] = p1[j];
				p1[j] = t[0];
			}
		}
	}
	//p2根据优先级数从高到低排序(若优先级数相同,则根据等待时间从大到小排序)
	for (int i = 0; i < p22-1; i++)
	{ 
		for (int j = 0; j < p22-1 - i; j++)
		{
			if (p2[j].super < p2[j + 1].super )
			{
				t[0]= p2[j + 1];
				p2[j + 1] = p2[j];
				p2[j] = t[0];
			}
			else if(p2[j].super == p2[j + 1].super)
			{
				if(p2[j].wait < p2[j + 1].wait )
				{
					t[0] = p2[j + 1];
				    p2[j + 1] = p2[j];
				    p2[j] = t[0];
				}
			}
			
		}
	}
	//将p1、p2按顺序赋值给进程结构体数组p
	int k=0;
	for(int i=0;i<=p11-1;i++)
	{
		p[k]=p1[i];
		k++;
	}
	for(int i=0;i<=p22-1;i++)
	{
		p[k]=p2[i];
		k++;
	}
	//释放空间 
	delete [] p1;
	delete [] p2;
	delete t;
}

int main ()
{
	int sumnum = 0,i,j; //sumnum表示执行所有进程总需的时间片长度
	printf("\n(^_^)请输入进程总个数:"); 
	scanf("%d",&N);
	printf("\n"); 
	P* p = new P[N]; //定义结构体数组 
	//通过循环输入进程信息,同时进行变量初始化 
	for(i = 0;i < N;i++)
	{
		printf("\n进程号No.%d:\n",i);
		printf("\n输入进程名:");
		scanf("%s",p[i].name);
		printf("\n输入进程优先数<0~99>:");
		scanf("%d",&(p[i].super));
		printf("\n输入进程运行时间:");
		scanf("%d",&(p[i].ndtime));
		p[i].wait = 0;
		p[i].runtime = 0;         
		p[i].jointime = i; 
		if(p[i].ndtime == 0)
			p[i].state = 'F';
		else 
			p[i].state = 'W';
	}
	//通过循环计算循环总次数 
	for(i = 0;i < N;i++) sumnum += p[i].ndtime; 
	
	//进行循环,对数组进行排序,在p数组从p2赋值过来的数组(即状态为“W”)的第一个数组的队列信息进行数据更新(即将需要运行的第一个进程进行运行) 
	int adjust=0;
	for(i = 0;i < sumnum;i++)
	{
		printf("\n按任意键继续......");
		getch();
		int k;
		printf("\n*-*-*-*-*-*-* The execute number: %d *-*-*-*-*-*-*\n",i + 1);
		Sort(p);  //排序 
		//通过循环,找到数组中需要运行的第一个进程 
		for(j = 0;p[j].state == 'F' && j < N;j++);
		//根据 j的范围来判断是否进程是否全部运行完,其实进程全部运行完后会跳出循环,程序不会再跑到这里 
		if(j < N)
		{
			p[j].state = 'R';
			p[j].super--;
			//防止优先级为负值
			if(p[j].super<0)
			{
				p[j].super=0;
				adjust=1;  //作为优先级数为 0的判断数,在进行后续输出时作为判断依据 
			}
			
			p[j].runtime++;
			p[j].wait = 0;
			//通过循环,将当前运行的进程的后面就绪进程的等待时间加一 
			for(k = j + 1;k < N;k++)
				p[k].wait++;
		}
		
		//打印当前运行进程的信息 
		printf("\n*-*-*-*-*-* 当前正在运行的进程是: %s *-*-*-*-*-*",p[j].name);
		printf("\np_name\tstate\tsuper\tndtime\truntime\t");
		printf("\n   |%s\t|%c\t|%d\t|%d\t|%d\n",p[j].name,
			p[j].state,adjust==1?p[j].super:p[j].super+1,p[j].ndtime,p[j].runtime-1);
		//打印此时就绪进程的信息 	
		printf("\n*-*-*-*-*-* 当前就绪队列状态为:  *-*-*-*-*-*\n");
		for(k = j + 1;k < N && i < sumnum - 1;k++)
			if(p[k].state != 'F')
			{
				printf("\np_name\tstate\tsuper\tndtime\truntime\t");
				printf("\n   |%s\t|%c\t|%d\t|%d\t|%d\n",p[k].name,
					p[k].state,p[k].super,p[k].ndtime,p[k].runtime);
			}
		//判断当前运行进程是否完成		
		if(p[j].ndtime == p[j].runtime)
		{
			p[j].state = 'F';
			printf("\n时间片到期,此时进程 [ %s ] 已完成.\n",p[j].name);
		}
		
		//需要再进行排序,因为完成队列可能更新 
		Sort(p);
		printf("\n*-*-*-*-*-* 当前完成队列状态为:  *-*-*-*-*-*\n");
		for(k = 0;k < j+1 && i < sumnum ;k++)
			if(p[k].state == 'F')
			{
				printf("\np_name\tstate\tsuper\tndtime\truntime\t");
				printf("\n   |%s\t|%c\t|%d\t|%d\t|%d\n",p[k].name,
					p[k].state,p[k].super,p[k].ndtime,p[k].runtime);
			}
			
		adjust=0; //依次循环后,优先级数是否为零的判断数重置为一 

	}
	
	printf("\n进程已经全部完成.\n");
    delete[] p;  //释放空间 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值