(王道408考研操作系统)第二章进程管理-第三节4:信号量机制(整型记录型信号量和PV操作)

Posted 我擦了DJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(王道408考研操作系统)第二章进程管理-第三节4:信号量机制(整型记录型信号量和PV操作)相关的知识,希望对你有一定的参考价值。

可以看出,不管是进程互斥的软件实现方法还是硬件实现方法,他们都无法解决“让权等待”这个问题,也即处理会处于会处于忙等状态。

而信号量则是一种功能较强的机制,可以有效的互斥与同步的问题

一:信号量是什么

信号量:本质就是一个变量(分为整形和记录型两种),表示系统中某种资源的数量。控制信号量有两种原子操作:

  • P操作(wait(S)原语):这个操作会把信号量减去1,相减后如果信号量<0则表示资源已经被占用,进程需要阻塞;相减后如果信号量 ≥ 0 \\ge0 0,则表明还有资源可以使用,进程可以正常执行
  • V操作(signal(S)原语):这个操作会把信号量加上1,相加后如果信号量 ≤ 0 \\le0 0,则表明当前有阻塞中的进程,于是会把该进程唤醒;相加后如果信号量>0,则表明当前没有阻塞中的进程

二:整型信号量

整型信号量:使用一个整型变量作为信号量,用来表示系统中某种资源的数量。比如某种资源S初始为1

int S=1;//初始信号量,表示当前系统中可用资源数

void wait(int S){//wait原语相当于进入区
	while(S<=0);//如果资源数不够,就一直循环等待
	S=S-1;//如果资源数够,就占用一个资源
}

void signal(int S){//signal原语,相当远退出区
	S=S+1;//使用完资源后释放资源,也即归还
}

具体描述:有如下进程

  • 对于进程 P 0 P_{0} P0,它想要使用资源S,必须先进行P操作。此时由于S=1,所以不会被卡住,然后资源数减一,S=0
  • 此时产生了进程切换,对于 P 1 P_{1} P1它也想要使用资源S,,必须先进行 P P P操作。不过此时S=0,所以 P 1 P_{1} P1它会被卡在循环那里,直到P_{0}进程释放资源
  • 其他进程也和 P 2 P_{2} P2一样
  • P 0 P_{0} P0进程执行完临界区代码后,在退出区执行V操作,归还资源,此时S=1
  • 由于 P 0 P_{0} P0释放了资源,所以 P 1 P_{1} P1进程此时从卡住的地方脱离开来继续向下进行P操作。后续进程亦是如此

缺陷:不满足让权等待,会发生忙等

三:记录型信号量

记录型信号量:除了需要使用一个用于代表资源数目的整形变量value外,还需要增加一个进程链表L,用于链接所有等待该资源的进程,使用一个指针指向。其用于记录的数据结构为:

typedef struct
{
	int value;//剩余资源数目
	struct process* L;//等待队列
}semaphore;

对应P操作和V操作

1:某进程需要使用资源时,需要进行P操作

void wait(semaphore S)
{
	S.value--;
	if(S.value < 0)
	{
		block(S.L);
	}
}
  • 执行了P操作,资源数量减一
  • 然后进行判断,如果<0那么表示没有系统资源了,所以是没有办法分配给当前申请该种资源的进程的,所以使用block原语使进程从运行态进入阻塞态,并将其挂到信号量为S的阻塞队列中

2:某进程需要使用完资源时,需要进行V操作

void signal(semaphore S)
{
	S.value++;
	if(S.value<=0)
	{
		wakeup(S.L);
	]
	
}
  • 执行了V操作,资源数量加一
  • 然后进行判断,如果<=0表示还有进程在等待这种资源,所以使用wakeup原语唤醒等待队列中的一个进程,该进程从阻塞态变为就绪态,并把它所等待的资源分配给它

具体描述:假设有2个系统资源,初始化时将信号量S的S.value设置为2,S.L设置为NULL,并有如下进程,它们都想要这种资源

  • 对于 P 0 P_{0} P0进程,执行完P操作后,S.value=1, P 0 P_{0} P0开始使用该资源
  • 切换到 P 1 P_{1} P1进程,执行完P操作后,S.value=0, P 1 P_{1} P1开始使用该资源
  • 切换到 P 2 P_{2} P2进程,执行完P操作后,S.value=-1,此时满足S.value<0,表示系统中没有多余资源可以分配,所以 P 2 P_{2} P2执行block原语, P 2 P_{2} P2被挂到等待队列中
  • 切换到 P 3 P_{3} P3进程,执行完P操作后,S.value=-2,此时满足S.value<0,表示系统中没有多余资源可以分配,所以 P 3 P_{3} P3执行block原语, P 3 P_{3} P3被挂到等待队列中
  • P 2 P_{2} P2 P 3 P_{3} P3目前都不可以进行服务
  • 此时切换到 P 0 P_{0} P0进程,执行完V操作后,S.value=-1,此时满足S.value<=0,表示等待队列中依然还有进程在等待资源,所以 P 0 P_{0} P0进程执行wakeup原语,唤醒 P 2 P_{2} P2进程(因为 P 2 P_{2} P2此时在等待队列队头), P 2 P_{2} P2由阻塞态转为就绪态,同时刚刚 P 0 P_{0} P0释放的资源会分配给 P 2 P_{2} P2
  • P 0 P_{0} P0在执行完毕之后,假如CPU继续再向 P 2 P_{2} P2服务, P 2 P_{2} P2开始使用资源,使用完毕之后,执行V操作,S.value=0,此时满足S.value<=0,表示等待队列中依然还有进程在等待资源,再利用wakeup原语唤醒 P 3 P_{3} P3 P 2 P_{2} P2释放的资源会分配给 P 3 P_{3} P3,等待队列为空
  • P 2 P_{2} P2在执行完毕之后,CPU为 P 1 P_{1} P1服务,执行V操作,S.value=1,此时不满足S.value<=0,表示等待队列中没有进程在等待资源,因此 P 1 P_{1} P1无需执行wakeup原语
  • 最后是 P 3 P_{3} P3,执行V操作,S.value=2 P 3 P_{3} P3结束

记录型信号量优点(总结):

S.value的初值表示系统中某种资源的数目;S.value如果为正表示目前系统中该资源还有剩余;S.value如果为负,那么其绝对值表示在等待队列中等待该资源的进程数目

  • P操作: 对信号量S的一次P操作意味着进程请求一个单位的该类资源,所以S.value--,表示资源数目少1。当S.value<0时表示该类资源已经分配完毕,因此进程应该调用block原语进行自我阻塞,主动放弃处理机,并插入到该类资源的等待队列S.L中。所以该机制遵循了让权等待原则,不会出现忙等现象
  • V操作: 对信号量S的一次V操作意味着进程释放一个单位的该类资源,所以S.value++,表示资源数目多1。如果加1之后仍然有S.value<=0,表示依然有进程在等待该类资源,因此应该调用wakeup原语唤醒等待队列中的第一个进程

以上是关于(王道408考研操作系统)第二章进程管理-第三节4:信号量机制(整型记录型信号量和PV操作)的主要内容,如果未能解决你的问题,请参考以下文章

(王道408考研操作系统)第二章进程管理-第三节8:经典同步问题之吸烟者问题

(王道408考研操作系统)第二章进程管理-第三节1:进程同步

(王道408考研操作系统)第二章进程管理-第三节7:经典同步问题之多生产者与多消费者问题

(王道408考研操作系统)第二章进程管理-第三节3:实现进程互斥的硬件方法

(王道408考研操作系统)第二章进程管理-第三节2:实现进程互斥的软件方法

(王道408考研操作系统)第二章进程管理-第三节4:信号量机制(整型记录型信号量和PV操作)