溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些

發(fā)布時(shí)間:2021-10-18 15:26:08 來源:億速云 閱讀:253 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

1. 什么是進(jìn)程通信

顧名思義,進(jìn)程通信( InterProcess Communication,IPC)就是指「進(jìn)程之間的信息交換」。實(shí)際上,「進(jìn)程的同步與互斥本質(zhì)上也是一種進(jìn)程通信」(這也就是待會(huì)我們會(huì)在進(jìn)程通信機(jī)制中看見信號(hào)量和 PV 操作的原因了),只不過它傳輸?shù)膬H僅是信號(hào)量,通過修改信號(hào)量,使得進(jìn)程之間建立聯(lián)系,相互協(xié)調(diào)和協(xié)同工作,但是它「缺乏傳遞數(shù)據(jù)的能力」。

雖然存在某些情況,進(jìn)程之間交換的信息量很少,比如僅僅交換某個(gè)狀態(tài)信息,這樣進(jìn)程的同步與互斥機(jī)制完全可以勝任這項(xiàng)工作。但是大多數(shù)情況下,「進(jìn)程之間需要交換大批數(shù)據(jù)」,比如傳送一批信息或整個(gè)文件,這就需要通過一種新的通信機(jī)制來完成,也就是所謂的進(jìn)程通信。

再來從操作系統(tǒng)層面直觀的看一些進(jìn)程通信:我們知道,為了保證安全,每個(gè)進(jìn)程的用戶地址空間都是獨(dú)立的,一般而言一個(gè)進(jìn)程不能直接訪問另一個(gè)進(jìn)程的地址空間,不過內(nèi)核空間是每個(gè)進(jìn)程都共享的,所以「進(jìn)程之間想要進(jìn)行信息交換就必須通過內(nèi)核」。

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  

下面就來我們來列舉一下 Linux 內(nèi)核提供的常見的進(jìn)程通信機(jī)制:

  • 管道(也稱作共享文件)
  • 消息隊(duì)列(也稱作消息傳遞)
  • 共享內(nèi)存(也稱作共享存儲(chǔ))
  • 信號(hào)量和 PV 操作
  • 信號(hào)
  • 套接字(Socket)
 

2. 管道

 

匿名管道

各位如果學(xué)過 Linux 命令,那對(duì)管道肯定不陌生,Linux 管道使用豎線 | 連接多個(gè)命令,這被稱為管道符。

$ command1 | command2
 

以上這行代碼就組成了一個(gè)管道,它的功能是將前一個(gè)命令(command1)的輸出,作為后一個(gè)命令(command2)的輸入,從這個(gè)功能描述中,我們可以看出「管道中的數(shù)據(jù)只能單向流動(dòng)」,也就是半雙工通信,如果想實(shí)現(xiàn)相互通信(全雙工通信),我們需要?jiǎng)?chuàng)建兩個(gè)管道才行。

另外,通過管道符 | 創(chuàng)建的管道是匿名管道,用完了就會(huì)被自動(dòng)銷毀。并且,匿名管道只能在具有親緣關(guān)系(父子進(jìn)程)的進(jìn)程間使用,。也就是說,「匿名管道只能用于父子進(jìn)程之間的通信」。

在 Linux 的實(shí)際編碼中,是通過 pipe 函數(shù)來創(chuàng)建匿名管道的,若創(chuàng)建成功則返回 0,創(chuàng)建失敗就返回 -1:

int pipe (int fd[2]);
 

該函數(shù)擁有一個(gè)存儲(chǔ)空間為 2 的文件描述符數(shù)組:

  • fd[0] 指向管道的讀端,     fd[1] 指向管道的寫端
  • fd[1] 的輸出是     fd[0] 的輸入

粗略的解釋一下通過匿名管道實(shí)現(xiàn)進(jìn)程間通信的步驟:

1)父進(jìn)程創(chuàng)建兩個(gè)匿名管道,管道 1(fd1[0]fd1[1])和管道 2(fd2[0]fd2[1]);

?  

因?yàn)楣艿赖臄?shù)據(jù)是單向流動(dòng)的,所以要想實(shí)現(xiàn)數(shù)據(jù)雙向通信,就需要兩個(gè)管道,每個(gè)方向一個(gè)。

?  

2)父進(jìn)程 fork 出子進(jìn)程,于是對(duì)于這兩個(gè)匿名管道,子進(jìn)程也分別有兩個(gè)文件描述符指向匿名管道的讀寫兩端;

3)父進(jìn)程關(guān)閉管道 1 的讀端 fd1[0] 和 管道 2 的寫端 fd2[1],子進(jìn)程關(guān)閉管道 1 的寫端 fd1[1] 和 管道 2 的讀端 fd2[0],這樣,管道 1 只能用于父進(jìn)程寫、子進(jìn)程讀;管道 2 只能用于父進(jìn)程讀、子進(jìn)程寫。管道是用「環(huán)形隊(duì)列」實(shí)現(xiàn)的,數(shù)據(jù)從寫端流入從讀端流出,這就實(shí)現(xiàn)了父子進(jìn)程之間的雙向通信。

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  

看完上面這些講述,我們來理解下管道的本質(zhì)是什么:對(duì)于管道兩端的進(jìn)程而言,管道就是一個(gè)文件(這也就是為啥管道也被稱為共享文件機(jī)制的原因了),但它不是普通的文件,它不屬于某種文件系統(tǒng),而是自立門戶,單獨(dú)構(gòu)成一種文件系統(tǒng),并且只存在于內(nèi)存中。

簡(jiǎn)單來說,「管道的本質(zhì)就是內(nèi)核在內(nèi)存中開辟了一個(gè)緩沖區(qū),這個(gè)緩沖區(qū)與管道文件相關(guān)聯(lián),對(duì)管道文件的操作,被內(nèi)核轉(zhuǎn)換成對(duì)這塊緩沖區(qū)的操作」。

 

有名管道

匿名管道由于沒有名字,只能用于父子進(jìn)程間的通信。為了克服這個(gè)缺點(diǎn),提出了有名管道,也稱做 FIFO,因?yàn)閿?shù)據(jù)是先進(jìn)先出的傳輸方式。

所謂有名管道也就是提供一個(gè)路徑名與之關(guān)聯(lián),這樣,即使與創(chuàng)建有名管道的進(jìn)程不存在親緣關(guān)系的進(jìn)程,只要可以訪問該路徑,就能夠通過這個(gè)有名管道進(jìn)行相互通信。

使用 Linux 命令 mkfifo 來創(chuàng)建有名管道:

$ mkfifo myPipe
 

myPipe 就是這個(gè)管道的名稱,接下來,我們往 myPipe 這個(gè)有名管道中寫入數(shù)據(jù):

$ echo "hello" > myPipe
 

執(zhí)行這行命令后,你會(huì)發(fā)現(xiàn)它就停在這了,這是因?yàn)楣艿览锏膬?nèi)容沒有被讀取,只有當(dāng)管道里的數(shù)據(jù)被讀完后,命令才可以正常退出。于是,我們執(zhí)行另外一個(gè)命令來讀取這個(gè)有名管道里的數(shù)據(jù):

$ cat < myPipe
hello
   

3. 消息隊(duì)列

可以看出,「管道這種進(jìn)程通信方式雖然使用簡(jiǎn)單,但是效率比較低,不適合進(jìn)程間頻繁地交換數(shù)據(jù),并且管道只能傳輸無格式的字節(jié)流」。為此,消息傳遞機(jī)制(Linux 中稱消息隊(duì)列)應(yīng)用而生。比如,A 進(jìn)程要給 B 進(jìn)程發(fā)送消息,A 進(jìn)程把數(shù)據(jù)放在對(duì)應(yīng)的消息隊(duì)列后就可以正常返回了,B 進(jìn)程在需要的時(shí)候自行去消息隊(duì)列中讀取數(shù)據(jù)就可以了。同樣的,B 進(jìn)程要給 A 進(jìn)程發(fā)送消息也是如此。

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  

「消息隊(duì)列的本質(zhì)就是存放在內(nèi)存中的消息的鏈表,而消息本質(zhì)上是用戶自定義的數(shù)據(jù)結(jié)構(gòu)」。如果進(jìn)程從消息隊(duì)列中讀取了某個(gè)消息,這個(gè)消息就會(huì)被從消息隊(duì)列中刪除。對(duì)比一下管道機(jī)制:

  • 消息隊(duì)列允許一個(gè)或多個(gè)進(jìn)程向它寫入或讀取消息。
  • 消息隊(duì)列可以實(shí)現(xiàn)消息的     「隨機(jī)查詢」,不一定非要以先進(jìn)先出的次序讀取消息,也可以按消息的類型讀取。比有名管道的先進(jìn)先出原則更有優(yōu)勢(shì)。
  • 對(duì)于消息隊(duì)列來說,在某個(gè)進(jìn)程往一個(gè)隊(duì)列寫入消息之前,并不需要另一個(gè)進(jìn)程在該消息隊(duì)列上等待消息的到達(dá)。而對(duì)于管道來說,除非讀進(jìn)程已存在,否則先有寫進(jìn)程進(jìn)行寫入操作是沒有意義的。
  • 消息隊(duì)列的生命周期隨內(nèi)核,如果沒有釋放消息隊(duì)列或者沒有關(guān)閉操作系統(tǒng),消息隊(duì)列就會(huì)一直存在。而匿名管道隨進(jìn)程的創(chuàng)建而建立,隨進(jìn)程的結(jié)束而銷毀。

需要注意的是,消息隊(duì)列對(duì)于交換較少數(shù)量的數(shù)據(jù)很有用,因?yàn)闊o需避免沖突。但是,由于用戶進(jìn)程寫入數(shù)據(jù)到內(nèi)存中的消息隊(duì)列時(shí),會(huì)發(fā)生從用戶態(tài)「拷貝」數(shù)據(jù)到內(nèi)核態(tài)的過程;同樣的,另一個(gè)用戶進(jìn)程讀取內(nèi)存中的消息數(shù)據(jù)時(shí),會(huì)發(fā)生從內(nèi)核態(tài)拷貝數(shù)據(jù)到用戶態(tài)的過程。因此,「如果數(shù)據(jù)量較大,使用消息隊(duì)列就會(huì)造成頻繁的系統(tǒng)調(diào)用,也就是需要消耗更多的時(shí)間以便內(nèi)核介入」。

 

4. 共享內(nèi)存

為了避免像消息隊(duì)列那樣頻繁的拷貝消息、進(jìn)行系統(tǒng)調(diào)用,共享內(nèi)存機(jī)制出現(xiàn)了。

顧名思義,共享內(nèi)存就是允許不相干的進(jìn)程將同一段物理內(nèi)存連接到它們各自的地址空間中,使得這些進(jìn)程可以訪問同一個(gè)物理內(nèi)存,這個(gè)物理內(nèi)存就成為共享內(nèi)存。如果某個(gè)進(jìn)程向共享內(nèi)存寫入數(shù)據(jù),所做的改動(dòng)將「立即」影響到可以訪問同一段共享內(nèi)存的任何其他進(jìn)程。

集合內(nèi)存管理的內(nèi)容,我們來深入理解下共享內(nèi)存的原理。首先,每個(gè)進(jìn)程都有屬于自己的進(jìn)程控制塊(PCB)和邏輯地址空間(Addr Space),并且都有一個(gè)與之對(duì)應(yīng)的頁(yè)表,負(fù)責(zé)將進(jìn)程的邏輯地址(虛擬地址)與物理地址進(jìn)行映射,通過內(nèi)存管理單元(MMU)進(jìn)行管理。「兩個(gè)不同進(jìn)程的邏輯地址通過頁(yè)表映射到物理空間的同一區(qū)域,它們所共同指向的這塊區(qū)域就是共享內(nèi)存」

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  

不同于消息隊(duì)列頻繁的系統(tǒng)調(diào)用,對(duì)于共享內(nèi)存機(jī)制來說,僅在建立共享內(nèi)存區(qū)域時(shí)需要系統(tǒng)調(diào)用,一旦建立共享內(nèi)存,所有的訪問都可作為常規(guī)內(nèi)存訪問,無需借助內(nèi)核。這樣,數(shù)據(jù)就不需要在進(jìn)程之間來回拷貝,所以這是最快的一種進(jìn)程通信方式。

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  
 

5. 信號(hào)量和 PV 操作

實(shí)際上,對(duì)具有多 CPU 系統(tǒng)的最新研究表明,在這類系統(tǒng)上,消息傳遞的性能其實(shí)是要優(yōu)于共享內(nèi)存的,因?yàn)?strong>「消息隊(duì)列無需避免沖突,而共享內(nèi)存機(jī)制可能會(huì)發(fā)生沖突」。也就是說如果多個(gè)進(jìn)程同時(shí)修改同一個(gè)共享內(nèi)存,先來的那個(gè)進(jìn)程寫的內(nèi)容就會(huì)被后來的覆蓋。

并且,在多道批處理系統(tǒng)中,多個(gè)進(jìn)程是可以并發(fā)執(zhí)行的,但由于系統(tǒng)的資源有限,進(jìn)程的執(zhí)行不是一貫到底的, 而是走走停停,以不可預(yù)知的速度向前推進(jìn)(異步性)。但有時(shí)候我們又希望多個(gè)進(jìn)程能密切合作,按照某個(gè)特定的順序依次執(zhí)行,以實(shí)現(xiàn)一個(gè)共同的任務(wù)。

舉個(gè)例子,如果有 A、B 兩個(gè)進(jìn)程分別負(fù)責(zé)讀和寫數(shù)據(jù)的操作,這兩個(gè)線程是相互合作、相互依賴的。那么寫數(shù)據(jù)應(yīng)該發(fā)生在讀數(shù)據(jù)之前。而實(shí)際上,由于異步性的存在,可能會(huì)發(fā)生先讀后寫的情況,而此時(shí)由于緩沖區(qū)還沒有被寫入數(shù)據(jù),讀進(jìn)程 A 沒有數(shù)據(jù)可讀,因此讀進(jìn)程 A 被阻塞。

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  

因此,為了解決上述這兩個(gè)問題,保證共享內(nèi)存在任何時(shí)刻只有一個(gè)進(jìn)程在訪問(互斥),并且使得進(jìn)程們能夠按照某個(gè)特定順序訪問共享內(nèi)存(同步),我們就可以使用進(jìn)程的同步與互斥機(jī)制,常見的比如信號(hào)量與 PV 操作。

「進(jìn)程的同步與互斥其實(shí)是一種對(duì)進(jìn)程通信的保護(hù)機(jī)制,并不是用來傳輸進(jìn)程之間真正通信的內(nèi)容的,但是由于它們會(huì)傳輸信號(hào)量,所以也被納入進(jìn)程通信的范疇,稱為低級(jí)通信」

?  

下面的內(nèi)容和上篇文章【看完了進(jìn)程同步與互斥機(jī)制,我終于徹底理解了 PV 操作】中所講的差不多,看過的小伙伴可直接跳到下一標(biāo)題。

?  

信號(hào)量其實(shí)就是一個(gè)變量 ,我們可以用一個(gè)信號(hào)量來表示系統(tǒng)中某種資源的數(shù)量,比如:系統(tǒng)中只有一臺(tái)打印機(jī),就可以設(shè)置一個(gè)初值為 1 的信號(hào)量。

用戶進(jìn)程可以通過使用操作系統(tǒng)提供的一對(duì)原語來對(duì)信號(hào)量進(jìn)行操作,從而很方便的實(shí)現(xiàn)進(jìn)程互斥或同步。這一對(duì)原語就是 PV 操作:

1)「P 操作」:將信號(hào)量值減 1,表示「申請(qǐng)占用一個(gè)資源」。如果結(jié)果小于 0,表示已經(jīng)沒有可用資源,則執(zhí)行 P 操作的進(jìn)程被阻塞。如果結(jié)果大于等于 0,表示現(xiàn)有的資源足夠你使用,則執(zhí)行 P 操作的進(jìn)程繼續(xù)執(zhí)行。

可以這么理解,當(dāng)信號(hào)量的值為 2 的時(shí)候,表示有 2 個(gè)資源可以使用,當(dāng)信號(hào)量的值為 -2 的時(shí)候,表示有兩個(gè)進(jìn)程正在等待使用這個(gè)資源。不看這句話真的無法理解 V 操作,看完頓時(shí)如夢(mèng)初醒。

2)「V 操作」:將信號(hào)量值加 1,表示「釋放一個(gè)資源」,即使用完資源后歸還資源。若加完后信號(hào)量的值小于等于 0,表示有某些進(jìn)程正在等待該資源,由于我們已經(jīng)釋放出一個(gè)資源了,因此需要喚醒一個(gè)等待使用該資源(就緒態(tài))的進(jìn)程,使之運(yùn)行下去。

我覺得已經(jīng)講的足夠通俗了,不過對(duì)于 V 操作大家可能仍然有困惑,下面再來看兩個(gè)關(guān)于 V 操作的問答:

問:「信號(hào)量的值 大于 0 表示有共享資源可供使用,這個(gè)時(shí)候?yàn)槭裁床恍枰獑拘堰M(jìn)程」

答:所謂喚醒進(jìn)程是從就緒隊(duì)列(阻塞隊(duì)列)中喚醒進(jìn)程,而信號(hào)量的值大于 0 表示有共享資源可供使用,也就是說這個(gè)時(shí)候沒有進(jìn)程被阻塞在這個(gè)資源上,所以不需要喚醒,正常運(yùn)行即可。

問:「信號(hào)量的值 等于 0 的時(shí)候表示沒有共享資源可供使用,為什么還要喚醒進(jìn)程」?

答:V 操作是先執(zhí)行信號(hào)量值加 1 的,也就是說,把信號(hào)量的值加 1 后才變成了 0,在此之前,信號(hào)量的值是 -1,即有一個(gè)進(jìn)程正在等待這個(gè)共享資源,我們需要喚醒它。

信號(hào)量和 PV 操作具體的定義如下:

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  
 

互斥訪問共享內(nèi)存

兩步走即可實(shí)現(xiàn)不同進(jìn)程對(duì)共享內(nèi)存的互斥訪問:

  • 定義一個(gè)互斥信號(hào)量,并初始化為 1
  • 把對(duì)共享內(nèi)存的訪問置于 P 操作和 V 操作之間
Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  

「P 操作和 V 操作必須成對(duì)出現(xiàn)」。缺少 P 操作就不能保證對(duì)共享內(nèi)存的互斥訪問,缺少 V 操作就會(huì)導(dǎo)致共享內(nèi)存永遠(yuǎn)得不到釋放、處于等待態(tài)的進(jìn)程永遠(yuǎn)得不到喚醒。

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  
 

實(shí)現(xiàn)進(jìn)程同步

回顧一下進(jìn)程同步,就是要各并發(fā)進(jìn)程按要求有序地運(yùn)行。

舉個(gè)例子,以下兩個(gè)進(jìn)程 P1、P2 并發(fā)執(zhí)行,由于存在異步性,因此二者交替推進(jìn)的次序是不確定的。假設(shè) P2 的 “代碼4” 要基于 P1 的 “代碼1” 和 “代碼2” 的運(yùn)行結(jié)果才能執(zhí)行,那么我們就必須保證 “代碼4” 一定是在 “代碼2” 之后才會(huì)執(zhí)行。

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  

如果 P2 的 “代碼4” 要基于 P1 的 “代碼1” 和 “代碼2” 的運(yùn)行結(jié)果才能執(zhí)行,那么我們就必須保證 “代碼4” 一定是在 “代碼2” 之后才會(huì)執(zhí)行。

使用信號(hào)量和 PV 操作實(shí)現(xiàn)進(jìn)程的同步也非常方便,三步走:

  • 定義一個(gè)同步信號(hào)量,并初始化為當(dāng)前可用資源的數(shù)量
  • 在優(yōu)先級(jí)較     「高」的操作的     「后」面執(zhí)行 V 操作,釋放資源
  • 在優(yōu)先級(jí)較     「低」的操作的     「前」面執(zhí)行 P 操作,申請(qǐng)占用資源
Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  

配合下面這張圖直觀理解下:

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  
 

6. 信號(hào)

注意!「信號(hào)和信號(hào)量是完全不同的兩個(gè)概念」

信號(hào)是進(jìn)程通信機(jī)制中唯一的「異步」通信機(jī)制,它可以在任何時(shí)候發(fā)送信號(hào)給某個(gè)進(jìn)程。「通過發(fā)送指定信號(hào)來通知進(jìn)程某個(gè)異步事件的發(fā)送,以迫使進(jìn)程執(zhí)行信號(hào)處理程序。信號(hào)處理完畢后,被中斷進(jìn)程將恢復(fù)執(zhí)行」。用戶、內(nèi)核和進(jìn)程都能生成和發(fā)送信號(hào)。

信號(hào)事件的來源主要有硬件來源和軟件來源。所謂硬件來源就是說我們可以通過鍵盤輸入某些組合鍵給進(jìn)程發(fā)送信號(hào),比如常見的組合鍵 Ctrl+C 產(chǎn)生 SIGINT 信號(hào),表示終止該進(jìn)程;而軟件來源就是通過 kill 系列的命令給進(jìn)程發(fā)送信號(hào),比如 kill -9 1111 ,表示給 PID 為 1111 的進(jìn)程發(fā)送 SIGKILL 信號(hào),讓其立即結(jié)束。我們來查看一下 Linux 中有哪些信號(hào):

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  
 

7. Socket

至此,上面介紹的 5 種方法都是用于同一臺(tái)主機(jī)上的進(jìn)程之間進(jìn)行通信的,如果想要「跨網(wǎng)絡(luò)與不同主機(jī)上的進(jìn)程進(jìn)行通信」,那該怎么做呢?這就是 Socket 通信做的事情了(「當(dāng)然,Socket 也能完成同主機(jī)上的進(jìn)程通信」)。

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  

Socket 起源于 Unix,原意是「插座」,在計(jì)算機(jī)通信領(lǐng)域,Socket 被翻譯為「套接字」,它是計(jì)算機(jī)之間進(jìn)行通信的一種約定或一種方式。通過 Socket 這種約定,一臺(tái)計(jì)算機(jī)可以接收其他計(jì)算機(jī)的數(shù)據(jù),也可以向其他計(jì)算機(jī)發(fā)送數(shù)據(jù)。

從計(jì)算機(jī)網(wǎng)絡(luò)層面來說,「Socket 套接字是網(wǎng)絡(luò)通信的基石」,是支持 TCP/IP 協(xié)議的網(wǎng)絡(luò)通信的基本操作單元。它是網(wǎng)絡(luò)通信過程中端點(diǎn)的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機(jī)的 IP 地址,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機(jī)的 IP 地址,遠(yuǎn)地進(jìn)程的協(xié)議端口。

Socket 的本質(zhì)其實(shí)是一個(gè)編程接口(API),是應(yīng)用層與 TCP/IP 協(xié)議族通信的中間軟件抽象層,它對(duì) TCP/IP 進(jìn)行了封裝。它「把復(fù)雜的 TCP/IP 協(xié)議族隱藏在 Socket 接口后面」。對(duì)用戶來說,只要通過一組簡(jiǎn)單的 API 就可以實(shí)現(xiàn)網(wǎng)絡(luò)的連接。

Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些  
 

8. 總結(jié)

簡(jiǎn)單總結(jié)一下上面六種 Linux 內(nèi)核提供的進(jìn)程通信機(jī)制:

1)首先,最簡(jiǎn)單的方式就是「管道」,管道的本質(zhì)是存放在內(nèi)存中的特殊的文件。也就是說,內(nèi)核在內(nèi)存中開辟了一個(gè)緩沖區(qū),這個(gè)緩沖區(qū)與管道文件相關(guān)聯(lián),對(duì)管道文件的操作,被內(nèi)核轉(zhuǎn)換成對(duì)這塊緩沖區(qū)的操作。管道分為匿名管道和有名管道,匿名管道只能在父子進(jìn)程之間進(jìn)行通信,而有名管道沒有限制。

2)雖然管道使用簡(jiǎn)單,但是效率比較低,不適合進(jìn)程間頻繁地交換數(shù)據(jù),并且管道只能傳輸無格式的字節(jié)流。為此「消息隊(duì)列」應(yīng)用而生。消息隊(duì)列的本質(zhì)就是存放在內(nèi)存中的消息的鏈表,而消息本質(zhì)上是用戶自定義的數(shù)據(jù)結(jié)構(gòu)。如果進(jìn)程從消息隊(duì)列中讀取了某個(gè)消息,這個(gè)消息就會(huì)被從消息隊(duì)列中刪除。

3)消息隊(duì)列的速度比較慢,因?yàn)槊看螖?shù)據(jù)的寫入和讀取都需要經(jīng)過用戶態(tài)與內(nèi)核態(tài)之間數(shù)據(jù)的拷貝過程,「共享內(nèi)存」可以解決這個(gè)問題。所謂共享內(nèi)存就是:兩個(gè)不同進(jìn)程的邏輯地址通過頁(yè)表映射到物理空間的同一區(qū)域,它們所共同指向的這塊區(qū)域就是共享內(nèi)存。如果某個(gè)進(jìn)程向共享內(nèi)存寫入數(shù)據(jù),所做的改動(dòng)將立即影響到可以訪問同一段共享內(nèi)存的任何其他進(jìn)程。

對(duì)于共享內(nèi)存機(jī)制來說,僅在建立共享內(nèi)存區(qū)域時(shí)需要系統(tǒng)調(diào)用,一旦建立共享內(nèi)存,所有的訪問都可作為常規(guī)內(nèi)存訪問,無需借助內(nèi)核。這樣,數(shù)據(jù)就不需要在進(jìn)程之間來回拷貝,所以這是最快的一種進(jìn)程通信方式。

4)共享內(nèi)存速度雖然非???,但是存在沖突問題,為此,我們可以使用信號(hào)量和 PV 操作來實(shí)現(xiàn)對(duì)共享內(nèi)存的互斥訪問,并且還可以實(shí)現(xiàn)進(jìn)程同步。

5)「信號(hào)」和信號(hào)量是完全不同的兩個(gè)概念!信號(hào)是進(jìn)程通信機(jī)制中唯一的異步通信機(jī)制,它可以在任何時(shí)候發(fā)送信號(hào)給某個(gè)進(jìn)程。通過發(fā)送指定信號(hào)來通知進(jìn)程某個(gè)異步事件的發(fā)送,以迫使進(jìn)程執(zhí)行信號(hào)處理程序。信號(hào)處理完畢后,被中斷進(jìn)程將恢復(fù)執(zhí)行。用戶、內(nèi)核和進(jìn)程都能生成和發(fā)送信號(hào)。

6)上面介紹的 5 種方法都是用于同一臺(tái)主機(jī)上的進(jìn)程之間進(jìn)行通信的,如果想要跨網(wǎng)絡(luò)與不同主機(jī)上的進(jìn)程進(jìn)行通信,就需要使用 「Socket」 通信。另外,Socket 也能完成同主機(jī)上的進(jìn)程通信。

“Linux內(nèi)核提供的常見的進(jìn)程通信機(jī)制有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI