写在前面:

这一篇博客将讨论信号量(Semaphores)机制。将学习三种基本类型的信号量,然后将用信号量实现互斥与前趋两种进程关系。

该机制由荷兰学者 Dijkstra 提出,是一种卓有成效的进程同步工具。
在系统中,给予每一个进程一个信号量,代表每个进程目前的状态,未得到控制权的进程会在特定地方被强迫停下来,等待可以继续进行的信号到来。如果信号量是一个任意的整数,通常被称为计数信号量(Counting semaphore),或一般信号量(general semaphore);如果信号量只有二进制的0或1,称为二进制信号量(binary semaphore)。在linux系统中,二进制信号量(binary semaphore)又称互斥锁(Mutex)。——Wikipedia。

整型信号量:

最初由 Dijkstra 把整型信号量定义为一个用于表示资源数目的整型量 S,它与一般整型量不同,除初始化外,仅能通过两个标准的原子操作(Atomic Operation) wait(S)和 signal(S)来访问。这两个操作一直被分别称为 P、V 操作。wait操作是使进程等待,申请资源;signal操作是使资源释放。

其实就是利用整型数这样的一个数据结构来表示进程资源是否可用:

  • 当S<=0时,资源不可用;
  • 当S>0时,资源可用。

进一步,Wait(S)与Signal(S)操作可描述为:

wait(S): while S<=0 do no-op;S:=S-1;signal(S): S:=S+1;

wait(S)和 signal(S)是两个原子操作,因此,它们在执行时是不可中断的。亦即,当一个进程在修改某信号量时,没有其他进程可同时对该信号量进行修改。此外,在 wait 操作中,对 S 值的测试和做 S:=S-1 操作时都不可中断。

在整型信号量机制中的 wait 操作,只要是信号量 S≤0,就会不断地测试。因此,该机制并未遵循“让权等待”的准则,而是使进程处于“忙等”的状态。换句话说,一旦一个进程需要的资源不可用,那么进程就会一直等待,直到资源可用为止,相当于在火车上,想上厕所,但厕所现在有人,那么就会一直等到里面的人出来,然后去上厕所才行。而应该退出临界区。为了解决这一问题,提出了记录型信号量。

记录型信号量:

记录型信号量机制是一种不存在“忙等”现象的进程同步机制。但在采取了“让权等待”的策略后,又会出
现多个进程等待访问同一临界资源的情况。为此,在信号量机制中,除了需要一个用于代表资源数目的整型变量 value 外,还应增加一个进程链表指针 L,用于链接上述的所有等待进程。记录型信号量是由于它采用了记录型的数据结构而得名的。它所包含的上述两个数据项可描述为:

type semaphore=recordvalue: integer;L: list of process;end

相应地,wait(S)和 signal(S)操作可描述为:

procedure wait(S)var S:semaphore;beginS.value:=S.value-1;if S.value<0 then block(S.L);endprocedure signal(S)var S: semaphore;beginS.value:=S.value+1;if S.value<=0 then wakeup(S.L);end

在记录型信号量机制中,S.value 的初值表示系统中某类资源的数目,因而又称为资源信号量。如果 S.value 的初值为 1,表示只允许一个进程访问临界资源,此时的信号量转化为互斥信号量,用于进程互斥。当 S.value<=0 时,表示该类资源已分配完毕;当 S.value>0 时,表示该类资源可用。

每次 wait 操作,意味着进程请求一个单位的该类资源,使系统中可供分配的该类资源数减少一个,因此描述为 S.value:=S.value-1;当 S.value<0 时,表示该类资源已分配完毕,因此进程应调用 block 原语,进行自我阻塞,放弃处理机,并插入到信号量链表S.L 中。

每次 signal 操作,表示执行进程释放一个单位资源,使系统中可供分配的该类资源数增加一个,故 S.value:=S.value+1 操作表示资源数目加 1。若加 1 后仍是 S.value≤0,则表示在该信号量链表中,仍有等待该资源的进程被阻塞,故还应调用 wakeup 原语,将 S.L 链表中的第一个等待进程唤醒。

关于block与wakeup原语可参考:操作系统学习-4. 进程控制

AND型信号量:

上述的进程互斥问题,是针对各进程之间只共享一个临界资源而言的。在有些应用场合,是一个进程需要先获得两个或更多的共享资源后方能执行其任务。然而这些时候如果仍采用记录型信号量,会导致两个进程各占用一部分的共享资源,从而谁也不让谁,导致“死锁”。

例如:现有两个进程 A和 B,他们都要求访问共享数据 D 和 E。可为这两个数据分别设置用于互斥的信号量 Dmutex 和 Emutex,并令它们的初值都是 1。。相应地,在两个进程中都要包含两个对 Dmutex 和 Emutex 的操作,即:

process A: wait(Dmutex);wait(Emutex);
process B: wait(Emutex);wait(Dmutex);

若进程 A 和 B 按下述次序交替执行 wait 操作:

process A: wait(Dmutex); //于是 Dmutex=0
process B: wait(Emutex); //于是 Emutex=0
process A: wait(Emutex); //于是 Emutex=-1 A 阻塞
process B: wait(Dmutex); //于是 Dmutex=-1 B 阻塞

最后,进程 A 和 B 处于僵持状态。在无外力作用下,两者都将无法从僵持状态中解脱出来。我们称此时的进程 A 和 B 已进入死锁状态。显然,当进程同时要求的共享资源愈多时,发生进程死锁的可能性也就愈大。

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

在 wait 操作中,增加了一个“AND”条件,故称为AND 同步,或称为同时 wait 操作,即Swait(Simultaneous wait)定义如下:

Swait(S1,S2,…,Sn)if S1>=1 and … and Sn>=1 thenfor i:=1 to n doSi:=Si-1;endforelse当发现第一个Si<1就把该进程放入等待队列,并将其程序计数器置于Swait操作的开始位置。endif

同样的,同时signal操作,即Ssignal(Simultaneous signal)定义如下:

Ssignal(S1,S2,…,Sn)for i:=1 to n doSi:=Si+1;将所有等待Si的进程由等待队列取出放入到就绪队列。endfor;

这里有涉及到程序计数器的概念,程序计数器(Program Counter,PC)是用于存放下一条指令所在单元的地址的地方。当执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称为“取指令”。与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。此后经过分析指令,执行指令。完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。

利用信号量实现进程互斥:

为使多个进程能互斥地访问某临界资源,只须为该资源设置一互斥信号量 mutex,并设其初始值为 1,然后将各进程访问该资源的临界区 CS 置于 wait(mutex)和 signal(mutex)操作之间即可。

关于访问临界资源的循环进程可参考:操作系统学习-5. 进程同步 。

利用信号量实现进程互斥的进程可描述如下:

Var mutex: semaphore:=1;beginparbeginprocess 1: beginrepeatwait(mutex);critical sectionsignal(mutex);remainder seetionuntil false;endprocess 2: beginrepeatwait(mutex);critical sectionsignal(mutex);remainder sectionuntil false;endparendend

每个欲访问该临界资源的进程在进入临界区之前,都要先对 mutex 执行wait 操作,若该资源此刻未被访问,本次 wait 操作必然成功,进程便可进入自己的临界区;这时若再有其他进程也欲进入自己的临界区,此时由于对 mutex 执行 wait 操作定会失败,因而该进程阻塞,从而保证了该临界资源能被互斥地访问。

当访问临界资源的进程退出临界区后,又应对 mutex 执行 signal 操作,以便释放该临界资源。

在利用信号量机制实现进程互斥时应注意,wait(mutex)和 signal(mutex)必须成对地出现。
缺少 wait(mutex)将会导致系统混乱,不能保证对临界资源的互斥访问;
缺少 signal(mutex)将会使临界资源永远不被释放,从而使因等待该资源而阻塞的进程不能被唤醒。

用信号量实现前趋关系:

设有两个并发执行的进程 P1 和 P2。P1 中有语句 S1;P2 中有语句 S2。我们希望在 S1 执行后再执行 S2。

为实现这种前趋关系,我们只须使进程 P1 和 P2 共享一个公用信号量 S,并赋予其初值为 0,将 signal(S)操作放在语句 S1 后面;而在 S2 语句前面插入 wait(S)操作,即:

  • 在进程 P1 中,用 S1;signal(S);
  • 在进程 P2 中,用 wait(S);S2;

由于 S 被初始化为 0,这样,若 P2 先执行必定阻塞,只有在进程 P1 执行完 S1;signal(S);操作后使 S 增为 1 时,P2 进程方能执行语句 S2 成功。

同样,我们可以利用信号量,按照语句间的前趋关系(见下图),写出一个更为复杂的可并发执行的程序。


图1.前趋图举例


图中 S1,S2,S3,…,S6 是最简单的程序段(只有一条语句)。

为使各程序段能正确执行,应设置若干个初始值为“0”的信号量。如为保证 S1→S2,S1→S3的前趋关系,应分别设置信号量 a 和 b,同样,为了保证 S2→S4,S2→S5,S3→S6,S4→S6和 S5→S6,应设置信号量 c,d,e,f,g。进程描述如下:

Var a,b,c,d,e,f,g:semaphore: =0,0,0,0,0,0,0;beginparbeginbegin S1; signal(a); signal(b); end;begin wait(a); S2; signal(c); signal(d); end;begin wait(b); S3; signal(e); end;begin wait(c); S4; signal(f); end;begin wait(d); S5; signal(g); end;begin wait(e); wait(f); wait(g); S6; end;parendend

操作系统学习-6. 信号量相关推荐

  1. 操作系统学习体会之进程管理篇

    计算机基础知识的学习中,操作系统则是重中之重.继对微机原理和计算机组成原理的基础知识了解和学习后,对硬件和基础原理的理论有了初步的了解,结合在所在公司的项目中开发应用的经历和体会,进行了操作系统的学习 ...

  2. 操作系统学习记录20220405

    操作系统学习记录(三) 2.4.1 死锁的概念 1.死锁:各个进程为了竞争资源而互相等待对方进程里的资源,进而所有进程都阻塞.至少有两个或以上的进程发生死锁,且处于阻塞态. 2.饥饿:长期得不到某种资 ...

  3. 操作系统学习(八)进程同步与通信

    目录 学习建议: 基本内容: 一.概述: 二.进程的顺序性: 三.进程的并发性: 四.与时间有关的错误: 五.临界区的概念: 六.进程的互斥: (一)PV操作: (二)临界区的管理: (三)用PV操作 ...

  4. 哈工大李治军老师的操作系统学习笔记

    文章目录 1 什么是操作系统 2 操作系统启动 3 操作系统接口 命令行发生了什么? 图形按钮怎么回事? 操作系统接口(系统调用) 4 操作系统调用 不应该随意访问内核 怎么不让你访问内核 不让我访问 ...

  5. UC/OS III操作系统学习笔记

    UCOS操作系统学习笔记 1.UCOSIII任务 1.1任务管理 1.2 任务创建和删除.挂起和恢复 1.3 系统内部任务 2.UCOSIII中断和时间管理 2.1 中断管理 2.2 时间管理 3.U ...

  6. linux操作系统学习网站整理(100个)

    linux操作系统学习网站整理(100个) 评选出的这100个优秀站点,将按照下述20个类别作以评介: (一) 文件下载 (二) 幽默娱乐 (三) 相关新闻 (四) 通用硬体 (五) 专用硬体 (六) ...

  7. 嵌入式Linux操作系统学习规划,学习嵌入式开发需要哪些知识?

    嵌入式Linux操作系统学习规划 ARM+LINUX路线,主攻嵌入式Linux操作系统及其上应用软件开发目标: (1) 掌握主流嵌入式微处理器的结构与原理(初步定为arm9) (2) 必须掌握一个嵌入 ...

  8. 操作系统学习笔记-2.1.5线程概念和多线程模型

    操作系统学习笔记-2019 王道考研 操作系统-2.1.5线程概念和多线程模型 文章目录 5线程概念和多线程模型 5.1知识概览 5.2 什么是线程?为什么要引入线程? 5.3引入线程及之后,有什么变 ...

  9. 操作系统学习笔记-2.1.4进程通信

    操作系统学习笔记-2019 王道考研 操作系统-2.1.4进程通信 文章目录 4进程通信 4.1知识总览 4.2前置知识:什么是进程通信? 4.3共享存储 4.4 管道通信 4.5消息传递 4.6小结 ...

最新文章

  1. 大话中文文本分类之TextRNN_ATT
  2. 全连接条件随机场_最新:通沪铁路一期连接上海虹桥站和上海站,二期连接浦东机场和上海东站...
  3. 在Eclipse中运行hadoop程序
  4. NOIP2019 Emiya家今天的饭
  5. 算法之美 : 位运算
  6. no segments* file found in SimpleFSDirectory问题总结
  7. 关于cocoa框架,你所要知道的一切(苹果官方文档,cocoa框架核心竞争力,必须收藏!)...
  8. 惊叹jQuery(解决jQuery对象到DOM的转换)
  9. Nobot控件------拒绝机器人行为
  10. 【学习笔记】莫队算法
  11. iscsi多路径配置方式
  12. /etc/udev/rules.d/10-usbstorage.rules
  13. docker配置深度学习环境
  14. python全栈开发-Day3 字符串
  15. 简易的设计模式——桥梁模式
  16. SPSS16 视频教程 共17章全
  17. 【matlab】图像二值化---最大类间方差法
  18. 打坐是开发潜能的快速方法
  19. adams打不开提示msc license_adams安装后打不开
  20. 英语口语收集(三十七)

热门文章

  1. [Mysql教程系列]介绍一下MySQL语句设计规范以及其他规范
  2. BZOJ 2407: 探险/4398: 福慧双修
  3. mysql数据表出现Table is marked as crashed and should be repaired 解决办法
  4. Guava RateLimiter算法原理及源码解读
  5. BDP数据可视化 - 散点图
  6. 关于大学生洗澡方式不同调研报告——顶点计划四班五组尚梓杰
  7. 中国化的P2P金融都有哪些特色?
  8. CSS基本知识点整理(一)
  9. A.c 和B.c两个c文件中使用了两个相同名字的static变量
  10. 网站服务器高主频还是多核心,高主频还是多核心?实测揭晓高主频为何对游戏性能更有价值...