进程管理(4):信号量与管程

本文详细介绍了信号量和管程在进程管理中的作用,解释了为何引入信号量,以及信号量的概念、操作和实现。接着,讨论了信号量在解决同步互斥问题中的应用,包括实现临界区互斥访问和进程间同步。最后,引入了管程的基本概念,阐述了管程如何解决信号量使用中的问题,以及管程在实现生产者消费者问题中的应用,并对比了管程和管程的调度策略差异。
摘要由CSDN通过智能技术生成

进程管理(3):同步互斥中,我们提到,为了解决同步互斥问题,操作系统会提供一些高级抽象方法供应用进程调用,这样应用进程就不需要自己利用繁琐的软件方法来解决同步互斥了。存在三种高级抽象方法,分别是锁,信号量与条件变量,其中锁也在上面那篇中讨论过了,这里主要是讨论信号量与条件变量。同步互斥的层次结构如下图所示:

synchronization_methods

信号量

为什么要引入信号量?

前面我们已经用锁机制方便的解决了临界区的互斥访问问题了,但是锁机制似乎并不能适用于更一般的情况。例如操作系统某些资源是有多个的,可以让多个进程共同访问,只有当访问的进程多于资源数量的时候才对进程访问加以限制。很明显,对于这种情况,使用锁机制的结果是一次只能有一个进程访问资源,这无疑是对资源的一种浪费。

此外,锁机制只能解决进程间的互斥访问问题,并不能推广到进程间的同步问题。

因此,有必要引入一个新的机制,既可以合理地对多个资源进行分配,又可以同时兼顾同步与互斥问题。这就是引入信号量机制的原因。

什么是信号量?

信号量是操作系统提供的一种协调共享资源访问的方法。它采用一种简明的方法来协调多个资源的访问,即采用信号量来表示当前剩余的系统资源数量。如果有一个进程请求某个资源,则将该资源的信号量递减;反之,如果某个进程释放了资源,就将该资源的信号量递增。这里对信号量的操作都是被操作系统封装起来的,因此可以看到,信号量更多的是一种抽象数据类型,由一个整型变量和两个基本操作组成,通常用P操作和V操作来表示递减和递增,分别对应了荷兰语里面的尝试减少增加。由于PV操作的对象,即sem变量实质上也是一个共享变量,对它的访问是需要互斥进行的,因此这里的PV操作都需要是原子操作。

class Semaphore{
   
private:
	int sem;

public:
	void up();
	void down();
}

信号量的实现

为了实现信号量,主要就是需要实现它的两个成员函数downup

当一个进程请求资源时,首先应该检查sem当前的值,如果sem > 0,表示系统还有剩余的资源,则执行--sem并且将资源分配给请求进程;如果sem <= 0,则表示当前系统已经没有这种资源了,仍然执行--sem,表示新增了一个进程在等待这个资源。由于当前进程得不到它请求的资源,此时应该释放CPU的控制权,调度其他进程进入运行状态。为了在资源空闲时可以唤醒当前进程,可以对每个信号量设置一个等待队列,并且将等待该信号量的进程加入等待队列中。

当一个进程释放了它占用的资源时,首先应该执行++sem表示将一个资源归还给了操作系统。此时如果sem <= 0,则表示还有其他进程在等待这个资源,所以应该从等待队列中挑选一个进程,将其唤醒;否则,如果sem > 0,表示当前已经有空闲的资源了,所以没有进程在等待队列中,直接退出就可以了。

根据这里的分析,给出上面Semaphore类的伪代码实现:

class Semaphore{
   
private:
	int sem;
	WaitQueue q;

public:
	void up();
	void down();
}

void Semaphore::down(){
   
	--sem;
	if(sem < 0){
   
		add current process to q;
		schedule();
	}
}

void Semaphore::up(){
   
	++sem;
	if(sem <= 0){
   
		pick a process in q;
		wakeup_proc();
	}
}

需要指出的是,上面的代码只是示意而已,实际的实现中还有一些细节的部

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值