chapter 6 進程通訊

學ucos至事件管理,事件之間將會有對話,開始拿本操做系統的書輔助理論上的理解。數組

參考《操做系統之哲學原理》,做者 鄒恆明。安全

 

 

it's the map of this section.服務器

1 進程對白

進程對白就是一個進程發出某種數據信息,另一方接受數據信息,而這些數據信息經過一片共享的存儲空間進行傳遞。網絡

管道所佔空間能夠是內存,也能夠是磁盤。就像兩我的對白的媒介能夠是空氣,也能夠是線纜同樣。要建立一個管道,一個進程只須要調用管道建立的系統調用便可。該系統調用所作的事情就是在某種存儲介質上劃出一片空間,賦給其中一個進程寫的權利,另外一個進程讀的權利便可。數據結構

1.1 管道

從根本上說,管道是一個線性字節數組,相似文件。在其後談論到管道和記名管道的缺點是提到,管道和記名管道並非因此操做系統都支持,主要支持管道通訊方式的是UNIX和類UNIX的操做系統,這使我想起everything is file這話。socket

在程序裏面,建立管道須要使用系統調用popen()或者pipe()。popen()須要提供一個目標進程做爲參數,而後調用該函數的進程和給出目標進程之間建立一個管道。函數

建立時還須要提供一個參數代表管道類型——讀管道或者寫管道。而pipe()調用將返回兩個文件描述符,即一個用於識別文件流的整數,其中一個用於從管道進行讀操做,一個用於寫入管道。例如this

1 int pp[2];
2 pipe(pp);
3 
4 if(fork() == 0){
5     read(pp[0]);
6 }
7 else{
8     write(pp[1])
9 }    

管道的一個重要特色是使用管道的兩個進程之間必須存在某種關係。spa

 

1.2 記名管道

 若是在兩個不相關的進程(如兩個不一樣進程裏的進程)之間進行管理通訊,則須要使用記名管道。記名管道是一個有名字的通訊管道,與文件系統共享一個名字空間,即不能與其餘任何文件重名。操作系統

一個進程建立一個記名管道後,另一個進程可使用open來打開這個管道(五名管道不能使用open操做),從而與另一端交流。

記名管道的名稱由兩部分組成:計算機名和管道名。

對於同一主機來講,容許有多個同一命名管道的實例而且能夠由不一樣的進程打開,可是不一樣的管道都有屬於本身的管道緩衝區並且有本身的通訊環境,互不影響。命名管道能夠支持多個客戶端鏈接一個服務器端,命名管道客戶端不但能夠與本機上的服務通訊,也能夠同其餘主機上的服務通訊。

 

1.3 套接字

 套接字(socket)是另一種能夠用於進程間通訊的機制,其功能很是強大,能夠支持不一樣層面、不一樣應用、跨網絡的通訊。

使用套接字進行通訊須要雙方都建立一個套接字,其中一方做爲服務器方,另外一方做爲客戶方。 服務器方必須先建立一個服務器套接字,而後在該套接字上進行監聽,等待遠方的鏈接請求。 欲與服務器通訊的客戶則建立一個客戶套接字,而後向服務區的套接字發送鏈接請求。 服務器套接字在收到鏈接請求以後,將在服務器方機器上建立一個客戶套接字,與遠方的客戶機上的客戶套接字造成點到點的通訊通道。 以後,客戶方和服務器方就能夠經過send和recv命令在這個建立的套接字通道上進行交流了。

例子略。

這裏須要指出的是服務區套接字既不發送數據,也不接受數據(指不接受正常的用戶數據,而不是鏈接請求數據),而僅僅生產出客戶套接字。當其餘的客戶套接字發出一個鏈接請求時,咱們就建立一個客戶套接字。一旦建立了客戶套接字clientsocket,與客戶通訊的任務就交給了這個剛剛建立的客戶套接字。而本來的服務器套接字seversocket則回到其原來的監聽操做上。

 

由於其強大的功能,套接字有許多種類,不一樣的操做系統均支持或實現了某種套接字的功能。

而後做者blabla了套接字的類型,no interested, so just skip over.

2 進程電報——信號

管道和套接字同時也存在某些缺點。

首先,若是使用管道和套接字方式來通訊,必須事先在通訊的進程間創建鏈接(建立管道或者套接字),這須要消耗資源。

其次,通訊是自願的。即一方雖然能夠隨意向管道或者套接字發送信息,但對方卻能夠選擇接受的時機,這對發送方不是有利,若是應用到實時系統就違背了實時的原則。

再次,因爲創建消耗鏈接時間,一旦創建,咱們就想進行儘量多的通訊。而若是通訊的信息量微小,則用管道和套接字有就些浪費資源了。

 

所以咱們選擇用另一個機制,即信號,來應對上述的通訊需求:

  • 想迫使一方對咱們的通訊當即作出迴應;
  • 咱們不想事先創建任何鏈接,而是臨時以爲有須要與某個進程通訊;
  • 傳輸的信息量微小,使用管道或者套接字不划算。

 

在ucos裏,有信號,應該不存在管道和socket吧。

 

在計算機裏,信號就是一個內核對象,或者說是一個內核數據結構。發送方將該數據結構的內容填好,並指明該信號的目標進程後,發出特定的軟件中斷。操做系統接受到特定的中斷請求後,知道是有進程要發送信號,因而到特定的內核數據結構裏查找信號接收方,並進行通知。接到通知的進程則對信號進行相應處理。

 

3 進程旗語——信號量

做者在這裏把信號量比做旗語——引用了火車的一個例子。

在一條單軌鐵路上,任什麼時候候只能有一列列車行駛在上面。而管理這條鐵路的系統就是信號量。任什麼時候候一列火車須要要等到代表鐵路能夠行駛的信號後才能進入軌道。當一列列車進入單軌運行以後,須要將信號改成禁止進入,從而防止別的火車同時進入軌道。而當列車駛出單軌以後,則須要將信號變爲容許進入狀態。

在計算機裏,信號量實際上就是一個簡單整數。一個進程在信號量(原書沒有「」字)變爲0或者1的狀況下推動,而且將信號量(原書沒有「量」字)變爲1或者0來防止別的進程推動。

(就像一個使能信號,好比這裏的OS_EVENT_EN?

 1 #if (OS_EVENT_EN)
 2 void  OS_EventWaitListInit (OS_EVENT *pevent)
 3 {
 4 #if OS_LOWEST_PRIO <= 63
 5     INT8U  *ptbl;
 6 #else
 7     INT16U *ptbl;
 8 #endif
 9     INT8U   i;
10 
11 
12     pevent->OSEventGrp = 0;                      /* No task waiting on event                           */
13     ptbl               = &pevent->OSEventTbl[0];
14 
15     for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
16         *ptbl++ = 0;
17     }
18 }
19 #endif

)

須要注意的是,信號量不僅是一種通訊機制,更是一個同步機制。

4 進程擁抱——共享內存

管道、套接字、信號、信號量,雖然知足了多種通訊須要,但未考慮到兩個進程通訊須要共享大量數據。這時便引出"共享內存"這個概念。

共享內存就是兩個進程共同擁有同一片內存。對於這片內存中的任何內容,兩者都可以訪問。要實用共享內存進行通訊,一個進程須要首先建立一片內存空間專門做爲通訊用,而其餘進程則將該片內存映射到本身的(虛擬)地址空間。這樣,讀寫本身地址空間中對應共享內存的區域時,就是在和其餘進程進行通訊。如圖(來源自書本)

 

共享內存與管道的區別在於:

  • 使用共享內存機制通訊的兩個進程必須在同一臺物理機器上;
  • 其次,共享內存的訪問方式是隨機的,而不是隻能從一端寫,另外一端讀,所以其靈活性比管道和套接字大不少,可以傳遞的信息也複雜不少。

共享內存的缺點是管理複雜和安全性弱。

這裏須要注意的是,使用全局變量在同一個進程的進程間實現通訊不稱爲共享內存。

 

5 信件發送——消息隊列

消息隊列是一列具備頭和尾的消息排列。新來的消息放在隊列尾部,而讀取消息則從隊列頭部開始。如圖(來源於書本)

消息隊列和管道的區別在於:

  • 首先,他無需固定的讀寫進程,任何進程均可以讀寫(固然是有權限的進程);
  • 其次,他能夠同時支持多個進程,多個進程能夠讀寫消息隊列。即所謂的多對多,而不是管道的點對點;
  • 另外,消息隊列只在內存中實現;
  • 最後,它並不僅在unix和類unix操做系統中實現。幾乎全部主流操做系統都支持消息隊列。

6 其餘通訊機制

blabla,no interested

相關文章
相關標籤/搜索