T面試題:程式間的通訊方式有哪幾種?

陝西優就業發表於2019-11-08

程式間的通訊方式,其實我們一直在用它,但是我們都不會去注意它。如果碰到面試官問你知道多少種程式間的通訊方式,估計很多人都會有點懵。今天 陝西優就業小編就和大家來總結下程式間的通訊方式有哪些。

程式間通訊的7種方式:

1、管道/匿名管道(管道)

管道是半雙工的,資料只能向一個方向流動;需要雙方通訊時,需要建立起兩個管道。

只能用於父子程式或者兄弟程式之間(具有親緣關係的程式);

單獨構成一種獨立的檔案系統:管道對於管道兩端的程式而言,就是一個檔案,但它不是普通的檔案,它不屬於某種檔案系統,而是自立門戶,單獨構成一種檔案系統,並且只存在與記憶體中。

資料的讀出和寫入:一個程式向管道中寫的內容被管道另一端的程式讀出寫入的內容每次都新增在管道緩衝區的末尾,並且每次都是從緩衝區的頭部讀出資料。

(1)管道的實質:

管道的實質是一個核心緩衝區,程式以先進先出的方式從緩衝區存取資料,管道一端的程式順序的將資料寫入緩衝區,另一端的程式則順序的讀出資料。

該緩衝區可以看做是一個迴圈佇列,讀和寫的位置都是自動增長的,不能隨意改變,一個資料只能被讀一次,讀出來以後在緩衝區就不復存在了。

當緩衝區讀空或者寫滿時,有一定的規則控制相應的讀程式或者寫程式進入等待佇列,當空的緩衝區有新資料寫入或者滿的緩衝區有資料讀出來時,就喚醒等待佇列中的程式繼續讀寫。

(2)管道的侷限:

管道的主要侷限性正體現在它的特點上:

①只支援單向資料流;

②只能用於具有親緣關係的程式之間;

③沒有名字;

④管道的緩衝區是有限的(管道制存在於記憶體中,在管道建立時,為緩衝區分配一個頁面大小);

⑤管道所傳送的是無格式位元組流,這就要求管道的讀出方和寫入方必須事先約定好資料的格式,比如多少位元組算作一個訊息(或命令,或記錄)等等;

2、有名管道(FIFO)

匿名管道,由於沒有名字,只能用於親緣關係的程式間通訊。為了克服這個缺點,提出了有名管道(FIFO)。

有名管道不同於匿名管道之處在於它提供了一個路徑名與之關聯,以有名管道的檔案形式存在於檔案系統中,這樣,即使與有名管道的建立程式不存在親緣關係的程式,只要可以訪問該路徑,就能夠彼此透過有名管道相互通訊,因此,透過有名管道不相關的程式也能交換資料。

值的注意的是,有名管道嚴格遵循先進先出(first in first out),對匿名管道及有名管道的讀總是從開始處返回資料,對它們的寫則把資料新增到末尾。它們不支援諸如lseek的()等檔案定位操作。有名管道的名字存在於檔案系統中,內容存放在記憶體中。

匿名管道和有名管道總結:

(1)管道是特殊型別的檔案,在滿足先入先出的原則條件下可以進行讀寫,但不能進行定位讀寫。

(2)匿名管道是單向的,只能在有親緣關係的程式間通訊;有名管道以磁碟檔案的方式存在,可以實現本機任意兩個程式通訊。

(3)無名管道阻塞問題:無名管道無需顯示開啟,建立時直接返回檔案描述符,在讀寫時需要確定對方的存在,否則將退出如果當前程式向無名管道的一端寫資料,必須確定另一端有某一程式。

如果寫入無名管道的資料超過其最大值,寫操作將阻塞,如果管道中沒有資料,讀操作將阻塞,如果管道發現另一端斷開,將自動退出。

(4)有名管道阻塞問題:。有名管道在開啟時需要確實對方的存在,否則將阻塞即以讀方式開啟某管道,在此之前必須一個程式以寫方式開啟管道,否則阻塞此外,可以以讀寫(O_RDWR)模式開啟有名管道,即當前程式讀,當前程式寫,不會阻塞。

3、訊號(訊號)

訊號是Linux的系統中用於程式間互相通訊或者操作的一種機制,訊號可以在任何時候發給某一程式,而無需知道該程式的狀態。

如果該程式當前並未處於執行狀態,則該訊號就有核心儲存起來,知道該程式回覆執行並傳遞給它為止。

如果一個訊號被程式設定為阻塞,則該訊號的傳遞被延遲,直到其阻塞被取消是才被傳遞給程式。

Linux系統中常用訊號:

(1)SIGHUP:使用者從終端登出,所有已啟動程式都將收到該程式。系統預設狀態下對該訊號的處理是終止程式。

(2)SIGINT:程式終止訊號。程式執行過程中,按Ctrl+C鍵將產生該訊號。

(3)SIGQUIT:程式退出訊號。程式執行過程中,按Ctrl+\\鍵將產生該訊號。

(4)SIGBUS和SIGSEGV:程式訪問非法地址。

(5)SIGFPE:運算中出現致命錯誤,如除零操作、資料溢位等。

(6)SIGKILL:使用者終止程式執行訊號。shell下執行kill -9傳送該訊號。

(7)SIGTERM:結束程式訊號。shell下執行kill 程式pid傳送該訊號。

(8)SIGALRM:定時器訊號。

(9)SIGCLD:子程式退出訊號。如果其父程式沒有忽略該訊號也沒有處理該訊號,則子程式退出後將形成殭屍程式。

訊號來源:訊號是軟體層次上對中斷機制的一種模擬,是一種非同步通訊方式,,訊號可以在使用者空間程式和核心之間直接互動,核心可以利用訊號來通知使用者空間的程式發生了哪些系統事件,訊號事件主要有兩個來源:

硬體來源:使用者按鍵輸入Ctrl + C鍵退出,硬體異常如無效的儲存訪問等。

軟體終止:終止程式訊號,其他程式呼叫殺函式,軟體異常產生訊號。

訊號生命週期和處理流程:

(1)訊號被某個程式產生,並設定此訊號傳遞的物件(一般為對應程式的PID),然後傳遞給作業系統;

(2)作業系統根據接收程式的設定(是否阻塞)而選擇性的傳送給接收者,如果接收者阻塞該訊號(且該訊號是可以阻塞的),作業系統將暫時保留該訊號,而不傳遞,直到該程式解除了對此訊號的阻塞(如果對應程式已經退出,則丟棄此訊號),如果對應程式沒有阻塞,作業系統將傳遞此訊號。

(3)目的程式接收到此訊號後,將根據當前程式對此訊號設定的預處理方式,暫時終止當前程式碼的執行,保護上下文(主要包括臨時暫存器資料,當前程式位置以及當前CPU的狀態),轉而執行中斷服務程式,執行完成後在回覆到中斷的位置。當然,對於搶佔式核心,在中斷返回時還將引發新的排程。

4、訊息(訊息)佇列

訊息佇列是存放在核心中的訊息連結串列,每個訊息佇列由訊息佇列識別符號表示。

與管道(無名管道:只存在於記憶體中的檔案;命名管道:存在於實際的磁碟介質或者檔案系統)不同的是訊息佇列存放在核心中,只有在核心重啟(即,作業系統重啟)或者顯示地刪除一個訊息佇列時,該訊息佇列才會被真正的刪除。

另外與管道不同的是,訊息佇列在某個程式往一個佇列寫入訊息之前,並不需要另外某個程式在該佇列上等待訊息的到達延伸閱讀:訊息佇列Ç語言的實踐訊息佇列特點總結:

(1)訊息佇列是訊息的連結串列,具有特定的格式,存放在記憶體中並由訊息佇列識別符號標識。

(2)訊息佇列允許一個或多個程式向它寫入與讀取訊息。

(3)管道和訊息佇列的通訊資料都是先進先出的原則。

(4)訊息佇列可以實現訊息的隨機查詢,訊息不一定要以先進先出的次序讀取,也可以按訊息的型別讀取。比FIFO更有優勢。

(5)訊息佇列克服了訊號承載資訊量少,管道只能承載無格式位元組流以及緩衝區大小受限等缺。

(6)目前主要有兩種型別的訊息佇列:POSIX訊息佇列以及System V訊息佇列,系統V訊息佇列目前被大量使用。系統V訊息佇列是隨核心持續的,只有在核心重起或者人工刪除時,該訊息佇列才會被刪除。

5、共享記憶體(共享記憶體)

使得多個程式可以可以直接讀寫同一塊記憶體空間,是最快的可用IPC形式。是針對其他通訊機制執行效率較低而設計的。

為了在多個程式間交換資訊,核心專門留出了一塊記憶體區,可以由需要訪問的程式將其對映到自己的私有地址空間。程式就可以直接讀寫這一塊記憶體而不需要進行資料的複製,從而大大提高效率。

由於多個程式共享一段記憶體,因此需要依靠某種同步機制(如訊號量)來達到程式間的同步及互斥。

延伸閱讀:Linux支援的主要三種共享記憶體方式:mmap()系統呼叫,Posix共享記憶體,以及System V共享記憶體實踐

6、訊號量(訊號量)

訊號量是一個計數器,用於多程式對共享資料的訪問,訊號量的意圖在於程式間同步。

為了獲得共享資源,程式需要執行下列操作:

(1)建立一個訊號量:這要求呼叫者指定初始值,對於二值訊號量來說,它通常是1,也可是0。

(2)等待一個訊號量:該操作會測試這個訊號量的值,如果小於0,就阻塞也稱為P操作。

(3)掛出一個訊號量:該操作將訊號量的值加1,也稱為V操作。

為了正確地實現訊號量,訊號量值的測試及減1操作應當是原子操作為此,訊號量通常是在核心中實現的.Linux環境中,有三種型別:Posix的(可移植性作業系統介面)有用訊號量(使用Posix IPC名字標識),Posix基於記憶體的訊號量(存放在共享記憶體區中),系統V訊號量(在核心中維護)。這三種訊號量都可用於程式間或執行緒間的同步。

訊號量與普通整型變數的區別:

(1)訊號量是非負整型變數,除了初始化之外,它只能透過兩個標準原子操作:wait(semap),signal(semap); 來進行訪問;

(2)操作也被成為PV原語(P來源於荷蘭語proberen “測試”,V來源於荷蘭語verhogen “增加”,P表示透過的意思,V表示釋放的意思),而普通整型變數則可以在任何語句塊中被訪問;

訊號量與互斥量之間的區別:

(1)互斥量用於執行緒的互斥,訊號量用於執行緒的同步。這是互斥量和訊號量的根本區別,也就是互斥和同步之間的區別。

互斥:是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。

同步:是指在互斥的基礎上(大多數情況),透過其它機制實現訪問者對資源的有序訪問。

在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源

(2)互斥量值只能為0/1,訊號量值可以為非負整數。

也就是說,一個互斥量只能用於一個資源的互斥訪問,它不能實現多個資源的多執行緒互斥問題。訊號量可以實現多個同類資源的多執行緒互斥和同步。當訊號量為單值訊號量是,也可以完成一個資源的互斥訪問。

(3)互斥量的加鎖和解鎖必須由同一執行緒分別對應使用,訊號量可以由一個執行緒釋放,另一個執行緒得到。

7、套接字(插座)

套接字是一種通訊機制,憑藉這種機制,客戶/伺服器(即要進行通訊的程式)系統的開發工作既可以在本地單機上進行,也可以跨網路進行。也就是說它可以讓不在同一臺計算機但透過網路連線計算機上的程式進行通訊。

套接字是應用層和傳輸層之間的橋樑。

套接字是支援TCP / IP的網路通訊的基本操作單元,可以看做是不同主機之間的程式進行雙向通訊的端點,簡單的說就是通訊的兩方的一種約定,用套接字中的相關函式來完成通訊過程。

套接字特性:

套接字的特性由3個屬性確定,它們分別是:域,埠號,協議型別。

(1)套接字的域

它指定套接字通訊中使用的網路介質,最常見的套接字域有兩種:

一是AF_INET,它指的是網際網路網路。當客戶使用套接字進行跨網路的連線時,它就需要用到伺服器計算機的IP地址和埠來指定一臺聯網機器上的某個特定服務,所以在使用插座作為通訊的終點,伺服器應用程式必須在開始通訊之前繫結一個埠,伺服器在指定的埠等待客戶的連線。

另一個域AF_UNIX,表示UNIX檔案系統,它就是檔案輸入/輸出,而它的地址就是檔名。

(2)套接字的埠號

每一個基於TCP / IP網路通訊的程式(程式)都被賦予了唯一的埠和埠號,埠是一個資訊緩衝區,用於保留插槽中的輸入/輸出資訊,埠號是一個16位無符號整數,範圍是0-65535,以區別主機上的每一個程式(埠號就像房屋中的房間號),低於256的埠號保留給標準應用程式,比如POP3的埠號就是110,每一個套接字都組合進了IP地址,埠,這樣形成的整體就可以區別每一個套接字。

(3)套接字協議型別

因特網提供三種通訊機制:

一是流套接字,流套接字在域中透過TCP / IP連線實現,同時也是AF_UNIX中常用的套接字型別。流套接字提供的是一個有序,可靠,雙向位元組流的連線,因此傳送的資料可以確保不會丟失,重複或亂序到達,而且它還有一定的出錯後重新傳送的機制。

二個是資料包套接字,它不需要建立連線和維持一個連線,它們在域中通常是透過UDP / IP協議實現的。它對可以傳送的資料的長度有限制,資料包作為一個單獨的網路訊息被傳輸,它可能會丟失,複製或錯亂到達,UDP不是一個可靠的協議,但是它的速度比較高,因為它並一需要總是要建立和維持一個連線。

三是原始套接字,原始套接字,允許對較低層次的協議直接訪問,比如IP,ICMP協議,它常用於檢驗新的協議實現,或者訪問現有服務中配置的新裝置,因為RAW SOCKET可以自如地控制Windows下的多種協議,能夠對網路底層的傳輸機制進行控制,所以可以應用原始套接字來操縱網路層和傳輸層應用。

比如,我們可以透過RAW SOCKET來接收發向本機的ICMP,IGMP協議包,或者接收的TCP / IP棧不能夠處理的IP包,也可以用來傳送一些自定包頭或自定協議的IP包。網路監聽技術很大程度上依賴於SOCKET_RAW。

原始套接字與標準套接字的區別在於:原始套接字可以讀寫核心沒有處理的IP資料包,而流套接字只能讀取TCP協議的資料,資料包套接字只能讀取UDP協議的資料。因此,如果要訪問其他協議傳送資料必須使用原始套接字。

套接字通訊的建立:

伺服器端:

(1)首先伺服器應用程式用系統呼叫套接字來建立一個套接字,它是系統分配給該伺服器程式的類似檔案描述符的資源,它不能與其他的程式共享。

(2)然後,伺服器程式會給套接字起個名字,我們使用系統呼叫結合來給套接字命名。然後伺服器程式就開始等待客戶連線到這個套接字。

(3)接下來,系統呼叫聽來建立一個佇列並將其用於存放來自客戶的進入連線。

(4)最後,伺服器透過系統呼叫接受來接受客戶的連線。它會建立一個與原有的命名套接不同的新套接字,這個套接字只用於與這個特定客戶端進行通訊,而命名套接字(即原先的套接字)則被保留下來繼續處理來自其他客戶的連線(建立客戶端和服務端的用於通訊的流,進行通訊)。

客戶端:

(1)客戶應用程式首先呼叫套接字來建立一個未命名的套接字,然後將伺服器的命名套接字作為一個地址來呼叫連線與伺服器建立連線。

(2)一旦連線建立,我們就可以像使用底層的檔案描述符那樣用套接字來實現雙向資料的通訊(透過流進行資料傳輸)。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69902581/viewspace-2663213/,如需轉載,請註明出處,否則將追究法律責任。

相關文章