多道程序设计模拟——C语言实现

操作系统实验:模拟多道程序设计的运行,并且比较顺序执行和多道程序执行的所需要的时间。
程序的生命周期为:计算->IO操作->计算->结束

下面为C语言实现版本,模拟的三个程序单通道模式

/*
*   多道程序设计模拟
*   作者:hjz
*   时间:2020/11/8
*
*   本次为操作系统的实验,模拟了A,B,C三个程序的多道程序的执行,比较顺序执行和多道程序设计
*                       程序执行的顺序为:计算->IO操作->计算->结束,分为三段
*	例如:
*	A先计算30ms,再io操作40ms,再计算10ms。
*   B先计算60ms,再io操作30ms,再计算10ms。
*   A先计算20ms,再io操作40ms,再计算20ms。
*
*   本次实验只模拟了三个程序和单通道模式
*/
#include<stdio.h>
#include<stdlib.h>
#define true 1
#define false 0
#define CPU 2
#define IO -1

typedef struct {
	char id;//任务名称
	int cpu_time1;//第一次计算时间
	int cpu_time2;//第二次计算时间
	int io_time;//io操作时间
	short flag;//第一次是否已计算完,计算完为1
}pro;//程序结构体

typedef struct{
	pro* arr[3];//队列
	int first;//队头
	int last;//队尾
	int n;//元素数量
}queue;//队列

queue cpu_q;//cpu队列
queue io_q;//io队列

void init(pro*,pro*,pro*);
void input(pro*);
void run_seq();
void run_par();
int enqueue(pro*,int);
pro* dequeue(int);
int empty(int);
int full(int);
int back(int,pro*);

int main(){
	pro* pro_a;
	pro* pro_b;
	pro* pro_c;
	init(pro_a,pro_b,pro_c);
	run_seq();
	run_par();
	return 0;
}

/*
*   判定队列是否是空
*
*   参数:
*       i:为1判定cpu队列,否则为io队列
*   返回值:如果为空返回正数,否则返回0
*/
int empty(int i){
	if(i == CPU){
		return cpu_q.n == 0;
	}else{
		return io_q.n == 0;
	}
}

/*
*   判定队列是否满
*
*   参数:
*       i:为CPU判定cpu队列,否则为io队列
*   返回值:如果满返回正数,否则返回0
*/
int full(int i){
	if(i == CPU){
		return cpu_q.n == 3;
	}else{
		return io_q.n == 3;
	}
}

/*
*   入队操作
*
*   参数:
*       p:要入队的程序
*       i:为CPU入cpu队列,否则为io队列
*   返回值:如果正常入队返回1,否则返回0
*/
int enqueue(pro* p,int i){
	if(full(i)) return false;
	if(i == CPU){
		cpu_q.arr[cpu_q.last] = p;
		cpu_q.last = (cpu_q.last + 1) % 3;
		cpu_q.n++;
	}else{
		io_q.arr[io_q.last] = p;
		io_q.last = (io_q.last + 1) % 3;
		io_q.n++;
	}
	return true;
}

/*
*   出队操作
*
*   参数:
*       i:为1出cpu队列,否则为io队列
*   返回值:返回队头元素或NULL
*/
pro* dequeue(int i){
	if(empty(i)) return NULL;
	pro* temp;
	if(i == CPU){
	 	temp = cpu_q.arr[cpu_q.first];
	 	cpu_q.arr[cpu_q.first] = NULL;
	 	cpu_q.first = (cpu_q.first + 1) % 3;
	 	cpu_q.n--;
	}else{
		temp = io_q.arr[io_q.first];
	 	io_q.arr[io_q.first] = NULL;
	 	io_q.first = (io_q.first + 1) % 3;
	 	io_q.n--;
	}
	return temp;
}

/*
*   将元素添加到队列头
*
*   参数:
*       i:为CPU则添加到cpu队列,否则添加到io队列
*       p:要添加的任务
*   返回值:添加成功返回1
*/
int back(int i,pro* p){
	if(full(i)) return false;
	if(i == CPU){
		cpu_q.first = (cpu_q.first - 1) % 3;
		cpu_q.arr[cpu_q.first] = p;
		cpu_q.n++;
		return true;
	}else{
		io_q.first = (io_q.first - 1) % 3;
		io_q.arr[io_q.first] = p;
		io_q.n++;
		return true;
	}
	return false;
}

/*
*   程序计算时间和io时间初始化
*
*   参数:
*       p:要被初始化的程序
*/
void input(pro* p){
	printf("请输入程序%c第一次计算的时间:",p->id);
	scanf("%d",&(p->cpu_time1));
	printf("请输入程序%c所需要的io时间:",p->id);
	scanf("%d",&(p->io_time));
	printf("请输入程序%c第二次计算的时间:",p->id);
	scanf("%d",&(p->cpu_time2));
	p->flag = 0;
	putchar('\n');
}

/*
*   队列和多道程序初始化
*
*   参数:
*       a:被初始化程序1
*       b:被初始化程序2
*       c:被初始化程序3
*/
void init(pro* a,pro* b,pro* c){
	printf("---------程序初始化---------\n");
	a = (pro*)malloc(sizeof(pro));
	b = (pro*)malloc(sizeof(pro));
	c = (pro*)malloc(sizeof(pro));
	a->id = 'A';
	b->id = 'B';
	c->id = 'C';
	input(a);
	input(b);
	input(c);
	cpu_q.arr[0] = a;
	cpu_q.arr[1] = b;
	cpu_q.arr[2] = c;
	cpu_q.first = 0;
	cpu_q.last = 0;
	cpu_q.n = 3;
	io_q.first = 0;
	io_q.last = 0;
	io_q.n = 0;
}

/*
*   顺序执行模式
*/
void run_seq(){
	printf("---------顺序执行模式---------\n");
	int i,sum = 0;
	for(i = 0;i < 3;i++){
		printf("程序%c计算%dms,io%dms,计算%dms\n",
			cpu_q.arr[i]->id,cpu_q.arr[i]->cpu_time1,cpu_q.arr[i]->io_time,cpu_q.arr[i]->cpu_time2);
		sum = sum + cpu_q.arr[i]->cpu_time1 + cpu_q.arr[i]->io_time + cpu_q.arr[i]->cpu_time2;
	}
	putchar('\n');
	printf("总耗时%dms\n",sum);
}

/*
*   多道执行模式
*/
void run_par(){
	printf("---------多道程序模式---------\n");
	pro* temp,*temp1;
	int time,sum = 0;
	
	while(!empty(CPU)||!empty(IO)){
		//如果io队列为空,则进行计算
		if(empty(IO)){
			temp = dequeue(CPU);
			if(temp != NULL){
				time = (temp->flag == 0) ? (temp->cpu_time1) : (temp->cpu_time2);
				printf("程序%c计算%dms\n",temp->id,time);
				sum += time;
				if(temp->flag == 0) {//如果是第一次计算,放入io队列,否则该程序结束
					temp->flag = 1;
					enqueue(temp,IO);
				}
				else free(temp);
				continue;
			}
			exit(0);
		}
		//如果cpu队列为空,则进行io调度,io调度完成后继续完成计算至程序结束
		if(empty(CPU)){
			temp = dequeue(IO);
			if(temp != NULL){
				printf("程序%c进行io%dms\n",temp->id,temp->io_time);
				printf("程序%c计算%dms\n",temp->id,temp->cpu_time2);
				sum = sum + temp->io_time + temp->cpu_time2;
				free(temp);
				continue;
			}
			exit(0);
		}
		
		//如果io队列和cpu队列都不为空,则io操作和计算同时进行
		temp = dequeue(CPU);
		temp1 = dequeue(IO);
		if(temp->flag == 0) time = temp->cpu_time1 - temp1->io_time;
		else time = temp->cpu_time2 - temp1->io_time;
		
		if(time >= 0){
			if(temp->flag == 0){
				printf("程序%c计算%dms的同时,程序%c进行io%dms",temp->id,temp->cpu_time1,temp1->id,temp1->io_time);
				sum += temp->cpu_time1;
			}else{
				printf("程序%c计算%dms的同时,程序%c进行io%dms",temp->id,temp->cpu_time2,temp1->id,temp1->io_time);
				sum += temp->cpu_time2;
			}
			while(time > 0){//如果在io操作完成后,正在计算的程序还没完成计算,继续调度io队列中的下一个
				int temp_time;
				if(!empty(IO)){
					pro* temp2 = dequeue(IO);
					temp_time = temp2->io_time;
					if(temp_time > time){//如果下一个io操作所需的时间过长,则先进行一段io操作,再放回队首,下次再调度
						printf(",程序%c进行io%dms",temp2->id,time);
						temp2->io_time = temp2->io_time - time;
						back(IO,temp2);
						break;
					}
					else{
						printf(",程序%c进行io%dms",temp2->id,temp_time);
						time -= temp_time;
						enqueue(temp2,CPU);
					}
				}
				break;
			}
			enqueue(temp1,CPU);
			if(temp->flag == 0){
				temp->flag = 1;
				enqueue(temp,IO);//如果是第一次计算,则进入io队列
			}
			else free(temp);
			putchar('\n');
		}
		else{
			sum += temp1->io_time;
			if(temp->flag == 0){
				printf("程序%c计算%dms的同时,程序%c进行io%dms",temp->id,temp->cpu_time1,temp1->id,temp1->io_time);
			}else{
				printf("程序%c计算%dms的同时,程序%c进行io%dms",temp->id,temp->cpu_time2,temp1->id,temp1->io_time);
			}
			time = -time;
			while(time > 0){//如果计算完成后,io操作还在继续,则继续调度cpu队列
				int temp_time;
				if(!empty(CPU)){
					pro* temp2 = dequeue(CPU);
					temp_time = (temp2->flag == 0) ? (temp2->cpu_time1) : (temp2->cpu_time2);
					if(temp_time > time){
						printf(",程序%c计算%dms\n",temp2->id,time);
						if(temp2->flag == 0) temp2->cpu_time1 = temp2->cpu_time1 - time;
						else temp2->cpu_time2 = temp2->cpu_time2 - time;
						back(CPU,temp2);
						break;
					}
					else{
						printf(",程序%c计算%dms",temp2->id,temp_time);
						time -= temp_time;
						if(temp2->flag == 0){
							temp2->flag = 1;
							enqueue(temp2,CPU);
						}
						else free(temp2);
					}
				}
				break;
			}
			enqueue(temp1,CPU);//完成io操作后调入cpu队列
			if(temp->flag == 0){
				temp->flag = 1;
				enqueue(temp,IO);
			}
			else free(temp);
			putchar('\n');
		}
	}
	printf("总耗时%dms\n",sum);
}

注:该多道程序设计的时间并不是最优解,还可以进一步改进。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值