關於進程間的通信

進程間的通信:管道    信號量   消息隊列   socket套接字

管道:線性字節數組,類似文件,使用文件讀寫的方式進行訪問

管道分爲:

有名管道:fifio     相當於創建了一個文件,這個文件只要有權限的,所有人都能來訪問(不相關的進程也能進行數據的交換)

無名管道:pipe     只能由父子進程進行使用,返回兩個文件描述符

創建管道時系統調用popen()或者pipe(),popen需要提供一個目標進程作爲參數,然後再調用該函數的進程和目標進程之間創建一個管道,是有名管道。

管道和記名管道不是所有操作系統都支持,主要支持管道通信方式的是UNIX和類UNIX(如Linux的操作系統)

同一主機,一個管道可以被多個進程打開,多個管道之間互不影響,服務器端可以創建一個管道文件,然後,客戶端的進程可以通過open;來打開服務器的管道文件。

管道的一個特點是,使用管道的兩個線程之間必須存在某種關係,例如:使用popen()需要提供另一端進程的文件名,使用pipe()兩個進程必須隸屬於父子進程。

信號量:用來在進程的通信時表示現在進行到那個狀態了,而使另外一個進程進行下面的操作。

主要應用在同步機制中。

競爭:兩個或多個線程爭相執行同一段代碼或訪問同一資源的現象。

臨界區:共享代碼段或者資源的區域成爲臨界區。

原子操作如何實現:

P操作:                                                                     V操作

1)等待信號量取值變爲1                             1)將信號量的值設置爲1

2)將信號量的值設置位0                              2)叫醒在該信號量上面等待的

3)繼續往下執行                                           3)線程繼續往下執行

互斥鎖:爲了保證不同時訪問一個資源,使臨界區的代碼不同時被執行

加鎖是對臨界區加鎖。一個加鎖後,其他的在臨界區要進行等待。

爲什麼要進行加鎖:多線程會共享資源,爲了保證資源能夠互斥訪問,就必須給資源加鎖,擁有該資源鎖的線程才能訪問該資源,每隔對象都有自己的鎖。

開鎖的操作:打開鎖

閉鎖的操作有兩個步驟:1.等待鎖達到打開狀態。2.獲得鎖並鎖上。(閉鎖的兩個操作應該是原子操作,即不能再分開)

鎖的特性:鎖的初始狀態要是打開狀態,進入臨界區獲得鎖,出臨界區開鎖,等待其他的線程打開鎖

生產者與消費者模型:

sleep和wakeup就是操作系統裏的睡覺和叫醒操作原語,一個程序調用sleep後將進入休眠狀態,其所佔用的cpu將被釋放,一個執行wakeup的程序將發送一個信號給指定的接受進程,如wakeup(producer)就是發送一個信號給生產者。

模擬生產者和消費者模型:一個進程代表生產者,一個進程代表消費者,一片內存緩衝區代表商店,生產者生產的商品從一端放入緩衝區,消費者從另外一端獲取物品。

上述操作對count沒有進行保護,可能發生數據的競爭,即生產者和消費者同時對數據進行修改也就是死鎖狀態。

造成死鎖的條件:因爲系統資源不足       進程推進的順序不合適     資源分配不當

信號量:特殊的變量,可以進行原子減1(P操作,代表獲取資源,V操作,代表釋放資源)(信號量可用來解決生產者和消費者的同步問題)

先設置3個信號量:

mutex:一個二元信號量,用來防止兩個線程同時對緩衝區進行操作      初始值位1

full:記錄緩衝區裏商品的件數      初始值爲0

empty:記錄緩衝區裏空置空間的數量      初始值爲N(緩衝區的大小)

改進之後的生產者消費者程序:

消息隊列:一列具有頭和尾的消息排列,新來的消息放在隊列尾部,而讀取消息則從隊列頭部開始。

記名管道的一段是固定的進程。消息隊列的讀寫都是不固定的。可以支持多進程的讀寫,管道支持的是一點對點。消息隊列只在內存中出現。

共享內存:兩個進程共同擁有一片內存,這片內存中的任何內容,二者均可以進行訪問

使用全局變量在同一個進程的線程間實現通信的不是共享內存,是信號量。

要使共享內存進行通信,一個進程首先創建一片內存空間專門作爲通信用,而其他進程則將該片內存映射到自己的虛擬地址空間,這樣,讀寫自己地址空間中對應共享內存的區域時,就是在和其他進程進行通信。

共享內存的要求是他不是一個文件,在內存中,而記名管道是一個文件,在磁盤上。再次,共享內存要求多個進程將共享的那一段內存映射到自己的虛擬空間中。其次,共享內存的訪問時隨機的。不再是一段讀一端寫了。

socket套接字:

通信雙方都要建立一個套接字,服務器的套接字的端口是固定的,以方便客戶端進行連接。這需要綁定操作。然後執行監聽。客戶端鏈接上後,服務器段需要再生成一個新的客戶端套接字與其進行通信。從而建立了一個通信信道。

必須先建立連接後,才能通信,相當於打電話。建立連接非常耗時,所以小的通信量使用信號來處理。信號就是進程在收到一個信號的時候,立即作出迴應。

服務器套接字既不發送數據,也不接收數據(指不接受正常的用戶數據,而不是鏈接請求數據)

其他通信機制:

1.更好的共享數據,傳遞數據。

2.多個線程進行通信,使資源的安全性得到保證,因爲線程是進程的一段執行序列,所以線程之間的通信是必須的。

3.消息隊列和管道的結構是類似的,但消息隊列一般只能在內存中,而管道可以在文件中,管道在創建的時候是給出一個目標進程。而消息隊列可以讓任何程序進行訪問。
4.是一個線性表

5.相同點是都需要建立一個通信信道,都可以支持不同主機的通信。但是管道不能代替套接字,服務器的套接字只是用來監聽是否有連接產生,處理的客戶端套接字用來處理連接。

6.應該是套接字。

7.管道,記名管道和套接字都必須進行通信信道 的建立。一般建立了信道就要多的進行數據傳遞。信號量和信號指示少量的數據進行傳遞。共享內存是爲了儘可能多的共享數據。消息隊列和管道類似,但是不需要指定目標進程。

參考《從哲學層次看操作系統》

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章