【操作系统】进程重点总结及习题

一.进程问题的重点总结

1.进程
①进程 = PCB(进程控制块,一种数据结构,形成环境封闭,使得并发运行的程序具有可再现性) + 程序的代码和数据
②进程是程序能够正确的并发执行的一种方式
③进程是一个独立运行的实体和单位
④进程具有动态的含义,进程和程序是不同的概念

2.进程的特征
①结构特征(PCB + 数据段 + 进程段 + 系统栈 + 用户栈 = 进程映像)
②动态性(创建产生、调度执行、撤销消亡)
③并发性
④独立性
⑤异步性

3.进程的状态及转化
在这里插入图片描述
4.进程的同步
①主要协调进程在运行次序上的关系,常引入信号量机制来完成协调。
②信号量的使用特点是:对同一信号量S,wait(S)和signal(S)出现在不同的进程中。

注:wait & signal = P & V, 在伪代码中写哪一组都可以,但是要注意必须搭配成对出现

5.进程的互斥
①多个进程在使用一个临界资源时必须以互斥的方式使用,在这部分信号量使用的特点是:对于一个互斥信号量M,PV操作一般必须成对出现在同一进程之中。
②在同步和互斥中,一个或多个进程的wait操作(P操作)顺序不能颠倒,否则将发生死锁
③一般先执行协调信号量的P操作,再执行互斥信号量的P操作,但多个V操作的排列顺序不影响进程的并发执行。

6.PV原语的详细解释
(1)PV原语简单介绍:
①定义:
PV原语通过操作信号量来处理进程间的同步与互斥的问题。其核心就是一段不可分割不可中断的程序。 信号量的概念1965年由著名的荷兰计算机科学家Dijkstra提出,其基本思路是用一种新的变量类型(semaphore)来记录当前可用资源的数量。

②semaphore
semaphore有两种实现方式:
semaphore的取值必须大于或等于0。0表示当前已没有空闲资源,而正数表示当前空闲资源的数量;semaphore的取值可正可负,负数的绝对值表示正在等待进入临界区的进程个数。

信号量定义操作(伪码)

structure semaphore{
	int count;
	queueType queue;
}

③P原语的操作(伪码)

void P(semaphore s){
	s.count--;
	if(s.count < 0){
		-阻塞当前进程;
		-把当前进程插入等待队列;
	}
}

④V原语的操作(伪码)

void V(semaphore s){
	s.count++;
	if(s.count <= 0){
		-把一个进程P从等待队列当中移除;
		-把进程P插到就绪队列;
	}
}

⑤利用信号量实现进程的互斥(类似于加锁)

/**/
const int n = /*进程数*/
semaphore s = 1; /*临界资源数量为1个*/
void process(int i){
	while(true){
	/*其他部分*/
	P(s);
	/*临界区*/
	V(s);
	/*其他部分*/
	}
} 

二.进程问题习题及解析(PV原语)

例1.某寺庙,有小和尚老和尚若干。有一水缸,由小和尚提水入缸供老和尚饮用。水缸可容10桶水,水取自同一井中。水井径窄,每次只能容下一个桶取水。水桶总数为3个。每人一次取缸水仅为1桶,且不可同时进行。试用记录信号量给出有关取水、入水的算法描述。

题目分析:
①3个水桶为临界资源需要互斥使用,定义并初始化信号量bucket=3。
②水井一次只能允许下一个水桶取水,定义并初始化互斥信号量well=1;
③水缸一次只能允许一个人取水,定义并初始化互斥信号量jar=1;
④empty和full用于老和尚与小和尚之间的制约关系,定义并初始化empty=10,开始时缸中没有水,因此full=0。
⑤这是一个生产者-消费者问题。小和尚取水条件需要确定:是否有桶、缸是否有人取水、缸是否为空、井是否能放桶。老和尚取水条件需要确定:是否有桶、缸是否有人取水、缸是否为空。

semaphore bucket = 3, jar = 1, well = 1, empty = 10, full = 0;
/*小和尚入水算法*/
young_monk(){
	while(1){
		/*查看缸中是否有空位*/
		P(empty);
		/*查看是否有可用的桶*/
		P(bucket);
		/*满足以上两个条件后,看是否井中有桶,如果没有,则从从井中取水*/
		P(well);
			从井中取水;
		V(well);
		/*取水后倒入水缸*/
		P(jar);
			倒入水缸;
		V(jar);
		/*增加一个桶的信号量*/
		V(backet);
		/*增加一个缸中水的数目的信号量*/
		V(full);
	}
}
/*老和尚取水算法*/
old_monk(){
	while(1){
		/*查看桶是否有水*/
		P(full);
		/*查看是否有空桶*/
		P(backet);
		/*从水缸中取水,验证是否只有一个人在取水*/
		P(jar);
			从缸中取水;
		V(jar);
		/*增加一个空桶的信号量*/
		V(backet);
		/*增加一个缸中空位的信号量*/
		V(empty);
			从桶中倒出饮用;
	}
}

例2.设有3个进程A、B、C,其中A与B构成一对生产者与消费者(A为生产者,B为消费者),共享一个由n个缓冲区组成的缓冲池;B与C也构成一对生产者与消费者(此时B为生产者,C为消费者),共享另一个由m个缓冲区组成的缓冲池。用信号量机制协调它们的同步问题。

题目分析:
①A与B是一个生产者与消费者问题,缓冲池为n,因此定义并初始化一组full1=0,empty1=n,mutex1=1。
②B与C是一个生产者与消费者问题,缓冲池为m,因此定义并初始化一组full2=0,empty2=m,mutex2=1。
③其中,B既是生产者又是消费者,因此代码段中应该包含两个部分。

Semaphore full1 = 0, full2 = 0, empty1 = n, empty2= m, mutex1 = 1, mutex2 = 1;
int in1 = 0, out1 = 0, in2 = 0, out2 = 0;
Buffer buffer1[n], buffer2[m];
A( ){
	while(true){
	/*只有生产者部分*/
		to produce an item;
		P(empty1);
		P(mutex1);
			把产品放入buffer1[in1];
		in1 = (in1+1) mod n;
		V(mutex1);
		V(full1);
	}
}
//在没有特殊条件说明下,生产者部分和消费者部分可以颠倒,但是一般作为生产者在前,消费者在后。
B( ){
	while(true){
	/*生产者部分*/
		P(full1);
		P(mutex1);
			从buffer1[out1]获得产品;
			out1 = (out1+1) mod n;
		V(mutex1);
		V(empty1);
		
	/*消费者部分*/
		P(empty2);
		P(mutex2);
			把产品放入buffer2[in2];
			in2 = (in2+1) mod m;
		V(mutex2)
		V(full2);
	}
}
C( ){
	while(true){
	/*只有消费者部分*/
		P(full2);
		P(mutex2);
			从buffer2[out2]获得产品;
			out2 = (out2+1) mod m;
		V(mutex2);
		V(empty2);
	}
}

例3.桌上有一只盘子,每次只能放入一个水果。爸爸专向盘子里放苹果,妈妈专向盘子里面放橘子,唯一的儿子专吃盘子中的橘子,唯一的女儿专吃盘子中的苹果。仅当盘子空闲时,爸爸或妈妈才可向盘子里存放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿才可从盘子里取出一个水果。把爸爸、妈妈、儿子、女儿看作4个进程,请用信号量机制进行管理,使得4个进程能正确地并发执行。
题目分析:
①父亲与女儿是一个1:1的生产者与消费者问题,具有专属关系。母亲与儿子是一个1:1的生产者与消费者问题,具有专属关系。
②其中,盘子作为临界资源,其容量为1,这一点非常重要,因为采用一般的生-消问题来解决此问题会有代码冗余,因此初始化变量plate=1,将原有的empty与mutex合并,减少代码数量,更加简洁。

semaphore plate = 1, apple = 0, orange = 0
dad(){
	while(true){
		to prepare an apple;
		P(plate);
			to put the apple on the plate;
		V(apple);
	}
}
mom(){
	while(true){
		to prepare an orange;
		P(plate);
			to put the orange on the plate;
		V(orange);
	}
}
son(){
	while(true){
		P(orange);
			to get an orange from the plate;
		V(plate);
		to eat the orange;
 	}
}
daughter(){
	while(true){
		P(apple);
			to get the apple from the plate;
		V(plate);
		to eat the apple
	}
}

注:如果此问题中盘子的容量大于1,则它将变为普通的生产者和消费者问题,加入empty=n,并将plate改为mutex,再修改相应代码即可。

例4.读者写者优先问题:如果有多个进程要求读文件,这时又有进程要求写文件,则在当前所有的读完成后,应先完成写操作,然后才能读,且在写的过程中,如果有另一进程要求写操作,则在当前写结束后,应接着完成写操作,直到没有写进程时,才允许读。

题目分析:
①如果没有写进程,应该让读进程随便进出。
②一旦有写进程到来,则需要一个信号量,使得此后到来的读进程都阻塞等待。
③需要一个信号量,保证当前有读进程时,不允许写。
④如果有写进程到来,则保证当前读进程读完成后,才可以写。

semaphore readcount = 0, writecount = 0, readok = 1, rmutex = 1, wmutex = 1, mutex = 1;
/*
变量:
 readcount = 0,用于记录读者的数量。
 writecount = 0,用于记录写者的数量。
信号量:
 readok = 1,用于协调读和写,保证写到来时,新来的读阻塞。
 rmutex = 1,和读优先中的互斥变量作用相同。
 wmutex = 1,用于控制互斥访问writecount变量。
 mutex = 1, 用于控制互斥写操作。
 */
 
 /*读者问题*/
reader(){
	while(true){
		P(readok);
		P(rmutex);
			if readcount == 0
				P(mutext);
			readcount ++;
		V(rmutex);
		V(readok);
		to read;
 		P(rmutex);
			readcount --;
			if readcount == 0
				V(mutext);
		V(rmutex);
	}
}
/*写者问题*/
writer(){
	while(true){
		P(wmutex)
			if writecount == 0
				P(readok);
			writecount ++;
		V(wmutex);
		P(mutex);
		to write;
		V(mutex);
		P(wmutex);
			writecount --;
			if writecount == 0
			V(readok);
		V(wmutex);
	}
}
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值