操作系統--進程間的通信,同步和互斥等

進程通信

    概念進程間傳輸數據(交換信息)。

    常用方式:管道、有名管道、信號、信號量、消息隊列、共享內存、套接字。

    管道( pipe ):管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關係的進程間使用。進程的親緣關係通常是指父子進程關係。

   有名管道 (named pipe) : 有名管道也是半雙工的通信方式,但是它允許無親緣關係進程間的通信。

   信號 ( sinal ) : 信號是一種比較複雜的通信方式,用於通知接收進程某個事件已經發生。
   信號量( semophore ) : 信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作爲一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作爲進程間以及同一進程內不同線程之間的同步手段。

     信號量(semaphore)的數據結構爲一個值和一個指針,指針指向等待該信號量的下一個進程信號量的值與相應資源的使用情況有關。當它的值大於0時,表示當前可用資源的數量;當它的值小於0時,其絕對值表示等待使用該資源的進程個數。注意,信號量的值僅能由PV操作來改變。
   消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。消息隊列是一種比較高級的進程間通信方式,它真的可以在進程間傳遞消息。例:
進程A向消息隊列寫入一個包含變量內容的消息,B進程從隊列中讀出

   共享內存( shared memory ) :共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號兩,配合使用,來實現進程間的同步和通信。
  套接字( socket ) : 套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用於不同及其間的進程通信。


信號與信號量不同:他們都能用來同步和互斥,但前者是使用信號處理器來執行的,後者是使用P、V操作來實現,P表示通過的意思,V表示釋放的意思

進程間的聯繫:1.相交進程:多個併發進程在邏輯上的某種聯繫

                          2.無關進程:在邏輯上無任何聯繫的進程

相交進程之間的關係主要有兩種,同步與互斥。

關鍵術語:

臨界資源:系統中某些資源一次只允許一個進程使用,這樣的資源稱爲臨界資源。也叫共享資源或互斥資源。

臨界區:一個程序片段的集合,這些程序片段分散在不同進程中,對某個共享的數據結構(臨界資源)進行操作,在進程中設計的臨界資源的程序片段,每個進程訪問共享資源的那段代碼稱爲臨界區,通俗地講 就是問共享資源的那段程序,例如 堆棧操作中的get(top)或rel(blk)

同步(直接制約):指系統中一些進程需要相互合作,共同完成一項任務,比如一個進程運行到某一點時,需要另一個夥伴進程爲它提供消息,在未獲得消息之前,該進程會一直處於等待狀態,在獲得消息後被喚醒進入就緒狀態。

        典型的例子是公共汽車上司機與售票員的合作。只有當售票員關門之後司機才能啓動車輛,只有司機停車之後售票員才能開車門。司機和售票員的行動需要一定的協調。同樣地,兩個進程之間有時也有這樣的依賴關係,因此我們也要有一定的同步機制保證它們的執行次序。

     實現進程同步方式:使用信號量。 信號量的特點就是允許多個進程同時訪問,數量由資源數目決定。

互斥(間接制約):當一個進程在一個臨界區訪問共享資源時,其他進程不能進入該臨界區訪問任何共享資源

      通常的情況是兩個或兩個以上的進程需要同時訪問某個共享變量。我們一般將發生能夠訪問共享變量的程序段成爲臨界區。兩個進程不能同時進入臨界區,否則就會導致數據的不一致,產生與時間有關的錯誤。解決互斥問題應該滿足互斥和公平兩個原則,即任意時刻只能允許一個進程處於同一共享變量的臨界區,而且不能讓任一進程無限期地等待。

      實現臨界區互斥基本方法可以用硬件方法或者軟件方法

      通過硬件實現臨界區最簡單的辦法就是關CPU的中斷。從計算機原理我們知道,CPU進行進程切換是需要通過中斷來進行。如果屏蔽了中斷那麼就可以保證當前進程順利的將臨界區代碼執行完,從而實現了互斥。這個辦法的步驟就是:屏蔽中斷--執行臨界區--開中斷。但這樣做並不好,這大大限制了處理器交替執行任務的能力。並且將關中斷的權限交給用戶代碼,那麼如果用戶代碼屏蔽了中斷後不再開,那系統豈不是跪了?還有硬件的指令實現方式,這個方式和接下來要說的信號量方式如出一轍。但是通過硬件來實現,這裏就不細說了。

    信號量實現方式

    這也是我們比較熟悉P V操作。通過設置一個表示資源個數的信號量S,通過對信號量S的P和V操作來實現進程的的互斥。P和V操作分別來自荷蘭語Passeren和Vrijgeven,分別表示佔有和釋放。P V操作是操作系統的原語,意味着具有原子性。 P操作首先減少信號量,表示有一個進程將佔用或等待資源,然後檢測S是否小於0,如果小於0則阻塞,如果大於0則佔有資源進行執行。 V操作是和P操作相反的操作,首先增加信號量,表示佔用或等待資源的進程減少了1個。然後檢測S是否小於0,如果小於0則喚醒等待使用S資源的其它進程。



死鎖:兩個或者兩個以上的進程因其中的每個進程都在等待其他進程做完事情而不能繼續執行,即多個進程互不相讓,都得不到足夠資源


信號量與互斥鎖的區別

“信號量用在多線程多任務同步的,一個線程完成了某一個動作就通過信號量告訴別的線程,別的線程再進行某些動作(大家都在semtake的時候,就阻塞在 哪裏)。而互斥鎖是用在多線程多任務互斥的,一個線程佔用了某一個資源,那麼別的線程就無法訪問,直到這個線程unlock,其他的線程纔開始可以利用這 個資源。比如對全局變量的訪問,有時要加鎖,操作完了,在解鎖。有的時候鎖和信號量會同時使用的”
也就是說,信號量不一定是鎖定某一個資源,而是流程上的概念,比如:有A,B兩個線程,B線程要等A線程完成某一任務以後再進行自己下面的步驟,這個任務 並不一定是鎖定某一資源,還可以是進行一些計算或者數據處理之類。而線程互斥量則是“鎖住某一資源”的概念,在鎖定期間內,其他線程無法對被保護的數據進 行操作。在有些情況下兩者可以互換。

兩者之間的區別:

作用域
信號量: 進程間或線程間(Linux僅線程間的無名信號量pthread semaphore)
互斥鎖: 線程間

上鎖時 
信號量: 只要信號量的value大於0,其他線程就可以sem_wait成功,成功後信號量的value減一。若value值不大於0,則sem_wait使得線程阻塞,直到sem_post釋放後value值加一,但是sem_wait返回之前還是會將此value值減一
互斥鎖: 只要被鎖住,其他任何線程都不可以訪問被保護的資源



發佈了29 篇原創文章 · 獲贊 40 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章