计算机操作系统之信号量机制

计算机操作系统之信号量机制

整型信号量

把整型信号量定义为一个用于表示资源数目的整型量S, 它与一般的整型量不同,除初始化外,仅通过两个标准的原子操作wait(s),和signal(s)来访问。这两个操作被称为P,V操作。

不遵循"让权等待"原则

wait(s)和signal(s)都是原子操作,不可中断

当一个进程在修改某信号量时,没有其他进程可以对信号量进行修改。

wait(s)  //p操作
{
	while(S<=0);   //如果可用资源数目不足,则原地等待;否则占用一个资源
	S--;
}
signal(S)  // v操作
{
	S++;  //释放资源
}

因为不遵循让权等待,所以在没有资源的时候会一直的在等待,使进程处于”忙等“状态。

记录型信号量

需要一种资源且只需要一个

在整型信号量的基础之上采用让权等待的策略之后,除一个整数值s.value外,还要一个进程等待队列s.queue(阻塞在该 信号量的各个进程的标识)。

PS: 信号量作为OS的核心代码执行,不受进程调度的打断,只能通过初始化和两个标准的原语(wait和signal)来访问。初始化一个非负整数的值,表示空闲资源的总数;(如果是负值,其绝对值表示当前等待临界区的进程数)

当S-*value<0时, 表示该类资源已分配完毕,因此进程应调用block原语进行自我阻塞, 放弃处理机, 并插入到信号量链表S>list中。可见, 该机制遵循了“让权等待”准则。此时S->value的绝对值表示在该信号量链表中已阻塞进程的数目。对信号量的每次signal操作表示执行进程释放一个单位资源,使系统中可供分配的该类资源数增加一个, 故S->value++操作表示资源数目加1。若加1后仍是S→value≤0,则表示在该信号量链表中仍有等待该资源的进程被阻塞,故还应调用wakeup原语, 将S->list链表中的第一个等待进程唤醒。如果S->value的初值为1,表示只允许一个进程访问临界资源,此时的信号量转化为互斥信号量,用于进程互斥。

//记录型信号量结构体
struct s{
	int value;
	List queue;
}
void wait(s)
{
	--value;  //表示申请一个资源
	if(s.value < 0)  //没有空闲资源
	s.queue;  //调用进程进入等待队列
	block;  //阻塞调用进程
}
void signal(s)
{
	++ s.value;  //释放一个资源
	if(s.value <= 0)  //表示有进程处于阻塞状态,则从阻塞队列的头部取出雇一个进程p;
	wakeup(); //唤醒进程p
}

AND型信号量

同时需要多种资源且每种资源占用一个

当两个进程m,n各需要资源a,b各3个时才能执行程进程,此时恰好资源a,b各恰好剩余3个,进程m有3个a,进程n有3个b,此时就会因为竞争临界资源造成一种僵持状态,无外力的情况下将无法解脱。

如果此时其中一个进程能够发挥"大爱精神",释放掉自己拥有的资源,就不会出现死锁。

AND同步机制的基本思想是:将进程在整个运行过程中需要的所有资源, 一次性全部地分配给进程,待进程使用完后再一起释放。只要尚有一个资源未能分配给进程,其它所有可能为之分配的资源也不分配给它。亦即,对若干个临界资源的分配采取原子操作方式:要么把它所请求的资源全部分配到进程,要么一个也不分配。由死锁理论可知,这样就可避免上述死锁情况的发生。为此, 在wait操作中增加了一个“AND”条件, 故称为AND同步, 或称为同时wait操作。

//p原语
swait(S1,S2,S3,...,Sn)
{
	while(true)
	{
		if(S1 >= 1 && S2 >= 1 && ... && Sn >= 1)  //满足全部资源要求时的处理;
		{
			for(i = 1; i <= n; ++i)  --Si;
			break;
		}
		else  //某些资源不够时的处理;
		{
			//调用进程进入第一个小于1信号量的等待队列
			Sj.queue;
			block;  //阻塞调用进程
		}
	}
}
//V原语S 
signal(S 1, S 2,·..fSn){
	while(TRUE) {
		for(i=1; i<=n;++i){
		++Si;//释放占用的资源;
		for(each process P waitingin Si.queue) { //检查每种资源的等待队列的所有进程;从等待队列si.queue中取出进程P;
				if(判断进程P是否通过S wait中的测试) {
				//注:与signal不同, 这里要进行重新判断;
				//通过检查(资源够用)时的处理;进程P进入就绪队列;}
				else{
					//未通过检查(资源不够用)时的处理;进程P进入某等待队列;
					}
		}
}

信号量集

用于同时需要多种资源,每种资源需要使用的数目不同,且可分配的资源存在一个临界值时的处理

在AND型信号量集的基础上进行扩充:进程对信号量Si的测试值为ti(用于信号量的判断,即Si>=ti,表示资源数量低于ti时,便不予分配)9占用值为di(用于信号量的增减,即Si=Si-di和Si=Si+di)

swait(S1,t1,d1,S2,t2,d3,S3,t3,d3,...,Sn,tn,dn)
{
	while(true)
	{
		if(S1 >= t1 && S2 >= t2 && ... && Sn >= tn)  //满足全部资源要求时的处理;
		{
			for(i = 1; i <= n; ++i)  Si = Si - di;
			break;
		}
		else  //某些资源不够时的处理;
		{
			//调用进程进入第一个小于1信号量的等待队列
			Sj.queue;
			block;  //阻塞调用进程
		}
	}
}
//V原语S 
signal(S1,d1,S2,d2,...,Sn,dn){
	while(TRUE) {
		for(i = 1; i <= n;++i){
		Si = Si + di;//释放占用的资源;
		for(each process P waitingin Si.queue) { //检查每种资源的等待队列的所有进程;从等待队列si.queue中取出进程P;
				if(判断进程P是否通过S wait中的测试) {
				//注:与signal不同, 这里要进行重新判断;
				//通过检查(资源够用)时的处理;进程P进入就绪队列;
				}
				else{
					//未通过检查(资源不够用)时的处理;进程P进入某等待队列;
					}
		}
}

特殊情况

Swait(S,d,d) :表示每次申请d个资源,当少于d个时不分配;

Swait(S,1,1) :蜕化为记录型信号量(S>1)或互斥信号量(S=1);

Swait(S,1,0) :作为一个可控开关当S>=1时,允计许多个进程进入临界区;

			}
	}

}


### 特殊情况

Swait(S,d,d) :表示每次申请d个资源,当少于d个时不分配;

Swait(S,1,1) :蜕化为记录型信号量(S>1)或互斥信号量(S=1);

Swait(S,1,0) :作为一个可控开关当S>=1时,允计许多个进程进入临界区;

当S=0时,,禁止任何进程进入临界区;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值