另附兩個對進程同步問題討論的鏈接:
linux 下進程間的同步機制有哪些?這兩天看進程的同步與通信,看了幾本書上的介紹,也從網上搜了很多資料,越看越迷惑,被這幾個問題搞得很糾結。
- 進程同步與互斥的區別?
- 進程的同步方式有哪些?
- 進程的通信方式有哪些?
- 進程同步與通信的區別是什麼?
- 線程的同步/通信與進程的同步/通信有區別嗎?
在好多教材上(包括國內與國外的)也沒有明確這些概念,現在對每個問題還沒有準確的答案,下面將自己的理解記下來,以後再補充。
參考資料:
《操作系統教程》 孫鍾秀主編 費翔林 駱斌 謝立參編 高等教育出版社
《計算機操作系統》 何炎祥 李飛 李寧 編著 清華大學出版社(進程管理部分與《操作系統教程》中的類似)
進程互斥、同步的概念
進程互斥、同步的概念是併發進程下存在的概念,有了併發進程,就產生了資源的競爭與協作,從而就要通過進程的互斥、同步、通信來解決資源的競爭與協作問題。
下面是根據《操作系統教程》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
共通之處是,信號量和消息(事件)
小結:
- 進程互斥、同步與通信的關係:進程競爭資源時要實施互斥,互斥是一種特殊的同步,實質上需要解決好進程同步問題,進程同步是一種進程通信,由此看來,進程互斥、同步都可以看做進程的通信;
-
信號量是進程同步與互斥的常用方法,也可以作爲低級的進程通信方法,用於傳遞控制信號;
-
管道與管程是不同的,管程是進程同步的方式,而管道則是進程通信的方式;