计算机操作系统-进程篇

计算机操作系统-进程篇:


内容:

  1. 进程同步作业
  2. 进程调度作业
  3. 调度算法-实训代码-C语言实现

1.进程同步作业

1.1 桌上有个能盛得下五个水果的空盘子,爸爸不停地向盘中放苹果或桔子,儿子不停地的从盘中取出桔子享用,女儿不停地从盘中取出苹果享用,规定三人不能同时从盘子中取放水果,试用信号量实现爸爸、儿子和女儿这三个循环进程之间的同步。

思路:

1.设置信号量:设爸爸的资源信号量为empty,初值为5,用来代表题目中所说的可以装下5个水果的空盘子;为儿女各设一个资源信号量,orange和apple,初值为0,表示刚开始时果盘为空;再设置一个互斥信号量mutex,初值为1(这个信号量最重要),用来规定三人不能同时从盘子中取放水果
2.爸爸在放水果前,先确定果盘是否有空位,执行wait(empty)操作,再进行互斥操作进入临界区,执行wait(mutex),都顺利进行的话,将水果放入果盘,再执行signal(mutex),释放临界区,对放入的水果进行判断,如果放的水果是橘子就唤醒儿子,反之则唤醒女儿
3.儿女在取水果前,先判断果盘是否存在相应的水果,执行wait(orange)或wait(apple)操作,再进行互斥操作进入临界区,执行wait(mutex),取走水果后退出临界区、唤醒爸爸
根据上述思路写出三个进程,在主进程内调用即可。parbegin、parend表示循环,也有些用cobegin、coend来表示,请根据自身情况而定。下图是老师强调的重点,上届考试有考
在这里插入图片描述

答案:

Semaphore empty, orange, apple , mutex;
empty.value=5; orange.value=0;
apple.value=0; mutex.value=1;
Dad( ){
While(1){
wait(empty);
wait(mutex);
将水果放入盘中;
signal(mutex);
if(放入的是桔子) signal(orange);
else signal(apple); }
}
Son( ){
While(1){
wait(orange);
wait(mutex);
从盘中取一个桔子;
signal(mutex);
signal(empty);
享用桔子;}
}
Daughter( ) {
While(1){
wait(apple);
wait(mutex);
从盘中取一个苹果;
signal(mutex);
signal(empty);
享用苹果;}
}
void main( ){
parbegin
Dad( ); Son( ); Daughter( );
parend }

1.2 试用记录型信号量写出一个不会死锁的哲学家进餐问题的算法

思路

根据P127页,哲学家就餐问题可采取3种方法进行解决
1.至多允许4个哲学家同时取左边的筷子,最终能保证至少有一位哲学家能够进行就餐,并在就餐完毕时能释放他用过的两根筷子,从而使更多哲学家能够就餐。
2.仅当哲学家的左右两根筷子均可用时,才允许进餐。
3.规定奇数号哲学家先拿左边筷子,然后再拿右边筷子;而偶数号哲学家则相反。按此规定1号、2号哲学家将竞争1号筷子;3号、4号哲学家竞争3号筷子。即5位哲学家都先竞争奇数号筷子,获得后,再竞争偶数号筷子,最后总会有一位哲学家能获得两根筷子而进餐。

1.2.1 规定至多允许4个哲学家同时取左边的筷子

semaphore chopstick[5] ,s;
chopstick[0].value=chopstick[1].value=1;
chopstick[2].value=chopstick[3].value=1 ;
chopstick[4].value=1 ; s.value=4;
process Pi( ) (i = 0,1,2,3,4){ //第i个哲学家的活动
while (1){
wait(s);
wait (chopstick[i]); //拿起左边筷子
wait (chopstick[(i+1)%5] ); //拿起右边筷子
eating ; //吃面条
signal (chopstick[i]); //放下左边筷子
signal (chopstick[(i+1)%5] );//放下右边筷子
signal(s);
thinking ;} //思考
}
void main( ){
parbegin
P0; P1( ); P2( ); P3; P4;
parend}

1.2.2 奇数号哲学家先拿左边筷子,然后再拿右边筷子;而偶数号哲学家先拿右边筷子,然后再拿左边筷子

semaphore chopstick[5] ;
chopstick[0].value=chopstick[1].value=1;
chopstick[2].value=chopstick[3].value=1 ;
chopstick[4].value=1 ;
process Pi( ) (i = 0,1,2,3,4){ //第i个哲学家的活动
while (1){
if(i%2= =1){
wait (chopstick[i]);
wait (chopstick[(i+1)%5] );
eating ;
signal (chopstick[i]);
signal (chopstick[(i+1)%5] );
thinking ; }
else{
wait (chopstick[(i+1)%5] );
wait (chopstick[i]);
eating ;
signal (chopstick[(i+1)%5] );
signal (chopstick[i]);
thinking ; }
}
}
void main( ){
cobegin
P0; P1( ); P2( ); P3; P4;
coend }


2.进程调度作业

熟悉、掌握以下各种进程(作业)调度算法的原理,计算填写下面的表格

在这里插入图片描述
在这里插入图片描述


3.实训代码

先来先服务(first come first service,FCFS)调度算法

是最简单的调度算法,该算法既可用于作业调度又可用于进程调度,按照作业到达的先后次序来进行调度,是一种非抢占式策略,但容易’饿死’短作业。详细说明请点击百度百科,或参考书本P79

短作业优先(Shortest Job First,SJF)调度算法

较FCFS算法有了明显的改进但仍存在不容忽视的缺点百度百科,或参考书本P79
当存在多个相同长度的短作业时,按照作业到达的先后次序来进行调度

代码如下:

#include <stdio.h>
#include <stdlib.h>
#define N 100
struct work {
	int number;//进程序号
	int starttime;//进程开始时间
	int servertime;//进程服务时间
	int overtime;//进程完成时间
	int ztime;//进程周转周期
	float qztime;//进程带权周转周期
};

void fcfs(struct work jc[],int n) {
	printf("即将进行先来先服务的算法:\n");
	struct work temp;
	for (int i=0; i<n; i++) {//到达时间排序
		for (int j=0; j<n-i-1; j++) {
			if(jc[j].starttime>jc[j+1].starttime) {
				temp=jc[j];
				jc[j]=jc[j+1];
				jc[j+1]=temp;
			}
		}
	}
	for (int i=0; i<n; i++) {
		if (i==0) jc[i].overtime=jc[i].starttime+jc[i].servertime;// 由于前面已排好到达时间升序,直接计算第一个完成时间即可 
		else jc[i].overtime=jc[i-1].overtime+jc[i].servertime;//剩下的拿前面的完成时间+自己的服务时间就可以得到完成时间 
		jc[i].ztime=jc[i].overtime-jc[i].starttime;//周转周期、带权周转周期没额外要求 
		jc[i].qztime=(float)jc[i].ztime/(float)jc[i].servertime;
		printf("进程序号:%-5d\t开始时间:%-5d\t服务时间:%-5d\t进程完成时间:%-5d\t进程周转周期:%-5d\t进程带权周转周期:%-5.3f\n",jc[i].number,jc[i].starttime,jc[i].servertime,jc[i].overtime,jc[i].ztime,jc[i].qztime);
	}
}
void sjf(struct work jc[],int n) {
	printf("即将进行短作业优先算法:\n");
	struct work temp;
	int index=0,endtime=0;
	for (int i=0; i<n-1; i++) {//到达时间升序
		for (int j=0; j<n-i-1; j++) {
			if(jc[j].starttime>jc[j+1].starttime) { 
				temp=jc[j];
				jc[j]=jc[j+1];
				jc[j+1]=temp;
			}

		}
	}
	for (int i=0; i<n; i++) {//对等待队列中的进程按照服务时间排序
		index=i;
		while(jc[i].starttime<=endtime && i<n) i++;//对从第i个之后的所有进程进行搜索,找到当前在等待的最后一个进程)
		for(int j=index; j<i; j++) {//对当前正在等待执行的进程按照服务时间排序
			for(int k=index+1; k<i; k++) {
				if(jc[j].servertime<jc[k].servertime) continue;
				else {
					temp=jc[j];
					jc[j]=jc[k];
					jc[k]=temp;
				}
			}
		}
		i=index;//将i的下标还原
		endtime+=jc[i].servertime;
	}
	for (int i=0; i<n; i++) {//根据前面的两次排序,结构体数组保存的值就直接像先来先服务一样做即可 
		if (i==0) jc[i].overtime=jc[i].starttime+jc[i].servertime;
		else jc[i].overtime=jc[i-1].overtime+jc[i].servertime;
		jc[i].ztime=jc[i].overtime-jc[i].starttime;
		jc[i].qztime=(float)jc[i].ztime/(float)jc[i].servertime;
		printf("进程序号:%-5d\t开始时间:%-5d\t服务时间:%-5d\t进程完成时间:%-5d\t进程周转周期:%-5d\t进程带权周转周期:%-5.3f\n",jc[i].number,jc[i].starttime,jc[i].servertime,jc[i].overtime,jc[i].ztime,jc[i].qztime);
	}
}
void wecome(){
	system("cls");//清屏
	printf("*************欢迎使用,请根据菜单输入序号,进行调用作业调度算法程序*************\n");
	printf("\n0.退出本程序\n");
	printf("\n1.先来先服务FCFS\n");
	printf("\n2.短作业优先SJF\n");
	printf("\n--------------------------------------------------------------------\n");
}
int main() {
	int n,x;
	printf("请输入有几个进程:");
	scanf("%d",&n);
	struct work fcfs_pro[n],sjf_pro[n];
	for (int i=0; i<n; i++) { //输入
		printf("请输入第%d个进程的进程序号,开始时间,服务时间:",i+1);
		scanf("%d%d%d",&fcfs_pro[i].number,&fcfs_pro[i].starttime,&fcfs_pro[i].servertime);
		sjf_pro[i]=fcfs_pro[i];//结构体数组复制
	}
	fcfs(fcfs_pro,n);
	sjf(sjf_pro,n);
	/*wecome();
	printf("\n请输入序号:");
	scanf("%d",&x);
	while (x !=EOF) {
		switch (x) {
			case 0:
				printf("欢迎下次再来");
				return 0;
			case 1:
				fcfs(fcfs_pro,n);
				printf("\nFCFS执行完毕,请输入序号,运行作业调度算法:");
				break;
			case 2:
				sjf(sjf_pro,n);
				printf("\n短作业优先SJF执行完毕,请输入序号,运行作业调度算法:");
				break;
			default:
				printf("输入不合法,请重新输入!\n请输入序号:");
		}
		scanf("%d",&x);
		wecome();
	}*/
	return 0;
}

效果

在这里插入图片描述


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值