本文转载自:http://www.cnblogs.com/youngforever/p/3250270.html
这两天看进程的同步与通信,看了几本书上的介绍,也从网上搜了很多资料,越看越迷惑,被这几个问题搞得很纠结。
- 进程同步与互斥的区别?
- 进程的同步方式有哪些?
- 进程的通信方式有哪些?
- 进程同步与通信的区别是什么?
- 线程的同步/通信与进程的同步/通信有区别吗?
在好多教材上(包括国内与国外的)也没有明确这些概念,现在对每个问题还没有准确的答案,下面将自己的理解记下来,以后再补充。
参考资料:
《操作系统教程》 孙钟秀主编 费翔林 骆斌 谢立参编 高等教育出版社
《计算机操作系统》 何炎祥 李飞 李宁 编著 清华大学出版社(进程管理部分与《操作系统教程》中的类似)
进程互斥、同步的概念
进程互斥、同步的概念是并发进程下存在的概念,有了并发进程,就产生了资源的竞争与协作,从而就要通过进程的互斥、同步、通信来解决资源的竞争与协作问题。
下面是根据《操作系统教程》3.1.4 中的介绍,整理的进程互斥、同步的概念。
在多道程序设计系统中,同一时刻可能有许多进程,这些进程之间存在两种基本关系:竞争关系和协作关系。
进程的互斥、同步、通信都是基于这两种基本关系而存在的,为了解决进程间竞争关系(间接制约关系)而引入进程互斥;为了解决进程间松散的协作关系( 直接制约关系)而引入进程同步;为了解决进程间紧密的协作关系而引入进程通信。
第一种是竞争关系
系统中的多个进程之间彼此无关,它们并不知道其他进程的存在,并且也不受其他进程执行的影响。例如,批处理系统中建立的多个用户进程, 分时系统中建立的多个终端进程。由于这些进程共用了一套计算机系统资源,因而, 必然要出现多个进程竞争资源的问题。当多个进程竞争共享硬设备、存储器、处理器 和文件等资源时,操作系统必须协调好进程对资源的争用。
资源竞争出现了两个控制问题:一个是死锁 (deadlock )问题,一组进程如果都获得了部分资源,还想要得到其他进程所占有的资源,最终所有的进程将陷入死锁。另一个是饥饿(starvation )问题,这是指这样一种情况:一个进程由于其他进程总是优先于它而被无限期拖延。
操作系统需要保证诸进程能互斥地访问临界资源,既要解决饥饿问题,又要解决死锁问题。
进程的互斥(mutual exclusion )是解决进程间竞争关系( 间接制约关系) 的手段。 进程互斥指若干个进程要使用同一共享资源时,任何时刻最多允许一个进程去使用,其他要使用该资源的进程必须等待,直到占有资源的进程释放该资源。
第二种是协作关系
某些进程为完成同一任务需要分工协作,由于合作的每一个进程都是独立地以不可预知的速度推进,这就需要相互协作的进程在某些协调点上协 调各自的工作。当合作进程中的一个到达协调点后,在尚未得到其伙伴进程发来的消息或信号之前应阻塞自己,直到其他合作进程发来协调信号或消息后方被唤醒并继续执行。这种协作进程之间相互等待对方消息或信号的协调关系称为进程同步。
进程间的协作可以是双方不知道对方名字的间接协作,例如,通过共享访问一个缓冲区进行松散式协作;也可以是双方知道对方名字,直接通过通信机制进行紧密协作。允许进程协同工作有利于共享信息、有利于加快计算速度、有利于实现模块化程序设计。
进程的同步(Synchronization)是解决进程间协作关系( 直接制约关系) 的手段。进程同步指两个以上进程基于某个条件来协调它们的活动。一个进程的执行依赖于另一
个协作进程的消息或信号,当一个进程没有得到来自于另一个进程的消息或信号时则需等待,直到消息或信号到达才被唤醒。
不难看出,进程互斥关系是一种特殊的进程同步关系,即逐次使用互斥共享资源,也是对进程使用资源次序上的一种协调。
进程通信的概念
下面是根据《操作系统教程》3.5 中的介绍,整理的进程通信的概念。
并发进程之间的交互必须满足两个基本要求:同步和通信。
进程竞争资源时要实施互斥,互斥是一种特殊的同步,实质上需要解决好进程同步问题,进程同步是一种进程通信,通过修改信号量,进程之间可建立起联系,相互协调运行和协同工作。但是信号量与PV操作只能传递信号,没有传递数据的能力。有些情况下进程之间交换的信息量虽很少,例如,仅仅交换某个状态信息,但很多情况下进程之间需要交换大批数据,例如,传送一批信息或整个文件,这可以通过一种新的通信机制来完成,进程之间互相交换信息的工作称之为进程通信IPC (InterProcess Communication)(主要是指大量数据的交换)。进程间通信的方式很多,包括:
- 信号(signal )通信机制;
- 信号量及其原语操作(PV、读写锁、管程)控制的共享存储区(shared memory )通信机制;
- 管道(pipeline)提供的共享文件(shared file)通信机制;
- 信箱和发信/ 收信原语的消息传递(message passing )通信机制。
其中前两种通信方式由于交换的信息量少且效率低下,故称为低级通信机制,相应地可把发信号/ 收信号及PV之类操作称为低级通信原语,仅适用于集中式操作系统。消息传递机制属于高级通信机制,共享文件通信机制是消息传递机制的变种,这两种通信机制,既适用于集中式操作系统,又适用于分布式操作系统。
进程同步的方法
前面提到,进程互斥关系是一种特殊的进程同步关系,下面给出常见的进程同步的方法,实际上也可用于进程的互斥(个人理解)。
在何炎祥的《计算机操作系统》 3.2 节,将进程同步的机制与解决进程互斥方法看做是一样的,的明确指出互斥的软件解决方法为Dekker算法与Peterson算法,互斥的硬件解决方法为中断方法、以及使用机器指令的方法,后面又给出了信号量、管程、消息传递三种方法。
实际应用中,不同的系统有不同的进程同步方法,CSDN帖子http://bbs.csdn.net/topics/80156687中有一些讨论,Linux 与Windows的主要同步、通信机制如下:
Linux 下:
Linux 下常见的进程同步方法有:SysVIPC 的 sem(信号量)、file locking / record locking(通过 fcntl 设定的文件锁、记录锁)、futex(基于共享内存的快速用户态互斥锁)。针对线程(pthread)的还有 pthread_mutex 和 pthread_cond(条件变量)。
Linux 下常见的进程通信的方法有 :pipe(管道),FIFO(命名管道),socket(套接字),SysVIPC 的 shm(共享内存)、msg queue(消息队列),mmap(文件映射)。以前还有 STREAM,不过现在比较少见了(好像)。
Windows下:
在Windwos中,进程同步主要有以下几种:互斥量、信号量、事件、可等计时器等几种技术。
在Windows下,进程通信主要有以下几种:内存映射、管道、消息等,但是内存映射是最基础的,因为,其他的进程通信手段在内部都是考内存映射来完成的。
线程的同步/通信与进程的同步/通信有区别吗?
对于该问题,教材上没有明确的回答,教材上给出的一般是进程而非线程的同步、通信方式。但网络上很多说法将两者混为一谈。根据教材,以及网上的说法,个人的理解为:
同步机制:
信号量、管程、互斥是进程的同步机制,而信号量、互斥也可用于线程的同步,但管程只在进程同步中被用到;
线程的同步除了信号量、互斥外,还有临界区、事件,没有看到教材上将这两种方式作为进程的同步方式;
通信机制:
管道、FIFO、消息队列、信号量、共享内存是进程的同步机制,教材上没有线程的通信机制这样的说法,但可以肯定这几种方法是进程的通信方式,且其中的信号量既可用于进程的同步,又可用于进程的通信,在网络上还有说可以用于线程同步的。
管道与管程是不同的,管程是进程同步的方式,而管道则是进程通信的方式。
进程的同步/通信
下面是常见的线程之间的同步方式的详细介绍。
(注:下面转自网络,下面的同步、通信方式对于进程与线程分的不是很清楚,关于进程还是线程的解释见上面——线程的同步/通信与进程的同步/通信有区别吗?)
一、进程/线程间同步机制。
临界区、互斥区、事件、信号量四种方式
临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)的区别
1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。
2、互斥量:采用互斥对象机制。
只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享 .互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
3、信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目 .
信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。
PV操作及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量S是一个整数,S大于等于零时代表可供并发进程使用的资源实体数,但S小于零时则表示正在等待使用共享资源的进程数。
P操作申请资源:
(1)S减1;
(2)若S减1后仍大于等于零,则进程继续执行;
(3)若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转入进程调度。
V操作 释放资源:
(1)S加1;
(2)若相加结果大于零,则进程继续执行;
(3)若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转入进程调度。
4、事 件: 通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作 .
总结:
1. 互斥量与临界区的作用非常相似,但互斥量是可以命名的,也就是说它可以跨越进程使用。所以创建互斥量需要的资源更多,所以如果只为了在进程内部是用的话使用临界区会带来速度上的优势并能够减少资源占用量。因为互斥量是跨进程的互斥量一旦被创建,就可以通过名字打开它。
2. 互斥量(Mutex),信号灯(Semaphore),事件(Event)都可以被跨越进程使用来进行同步数据操作,而其他的对象与数据同步操作无关,但对于进程和线程来讲,如果进程和线程在运行状态则为无信号状态,在退出后为有信号状态。所以可以使用WaitForSingleObject来等待进程和线程退出。
3. 通过互斥量可以指定资源被独占的方式使用,但如果有下面一种情况通过互斥量就无法处理,比如现在一位用户购买了一份三个并发访问许可的数据库系统,可以根据用户购买的访问许可数量来决定有多少个线程/进程能同时进行数据库操作,这时候如果利用互斥量就没有办法完成这个要求,信号灯对象可以说是一种资源计数器。
二、进程间通信方式
由于比较容易混淆,我们把进程间通信方法也列在这里做比较。
进程通信也就是所谓的IPC问题,主要是指进程间交换数据的方式。进程通信包括高级通信与低级通信,其中进程同步与互斥属于低级通信,主要用于插U农地控制信号;高级通信包括三种:共享存储系统(有的地方称作共享内存区)、消息传递系统(有的地方称作消息队列)、管道。
信号量是进程同步与互斥的常用方法,也可以作为低级的进程通信方法,用于传递控制信号。
简而言之,进程间通信方式主要包括管道、FIFO、消息队列、信号量、共享内存。
1.管道,还有命名管道和非命名管道(即匿名管道)之分,非命名管道(即匿名管道)只能用于父子进程通讯,命名管道可用于非父子进程,命名管道就是FIFO,管道是先进先出的通讯方式
2.消息队列,是用于两个进程之间的通讯,首先在一个进程中创建一个消息队列,然后再往消息队列中写数据,而另一个进程则从那个消息队列中取数据。需要注意的是,消息队列是用创建文件的方式建立的,如果一个进程向某个消息队列中写入了数据之后,另一个进程并没有取出数据,即使向消息队列中写数据的进程已经结束,保存在消息队列中的数据并没有消失,也就是说下次再从这个消息队列读数据的时候,就是上次的数据!!!!
3.信号量,它与WINDOWS下的信号量是一样的,所以就不用多说了
4.共享内存,类似于WINDOWS下的DLL中的共享变量,但LINUX下的共享内存区不需要像DLL这样的东西,只要首先创建一个共享内存区,其它进程按照一定的步骤就能访问到这个共享内存区中的数据,当然可读可写
以上几种方式的比较:
1.管道:速度慢,容量有限,只有父子进程能通讯
2.FIFO:任何进程间都能通讯,但速度慢
3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
4.信号量:不能传递复杂消息,只能用来同步
5.共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存
本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。一般说来,为了获得共享资源,进程需要执行下列操作:
套接字通信并不为Linux所专有,在所有提供了TCP/IP协议栈的操作系统中几乎都提供了socket,而所有这样操作系统,对套接字的编程方法几乎是完全一样的
三、进程/线程同步机制与进程间通信机制比较
很明显2者有类似,但是差别很大
同步主要是临界区、互斥、信号量、事件
进程间通信是管道、内存共享、消息队列、信号量、socket
共通之处是,信号量和消息(事件)
小结:
- 进程互斥、同步与通信的关系:进程竞争资源时要实施互斥,互斥是一种特殊的同步,实质上需要解决好进程同步问题,进程同步是一种进程通信,由此看来,进程互斥、同步都可以看做进程的通信;
-
信号量是进程同步与互斥的常用方法,也可以作为低级的进程通信方法,用于传递控制信号;
-
管道与管程是不同的,管程是进程同步的方式,而管道则是进程通信的方式;