小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Linux進(jìn)程間通信的實(shí)現(xiàn)原理?

 漢無(wú)為 2019-06-23

作為L(zhǎng)inux應(yīng)用程序的開(kāi)發(fā)人員,對(duì)Linux的進(jìn)程間通信方式肯定是了如指掌,平時(shí)的開(kāi)發(fā)中應(yīng)該會(huì)大量的使用到。當(dāng)你迅速的在鍵盤(pán)上按下【CTRL+C】終止掉一個(gè)正在運(yùn)行中的命令時(shí),你有沒(méi)有仔細(xì)的思考過(guò)背后的原理呢?或者是他們是通過(guò)什么通信方式呢?這個(gè)通信方式是怎樣實(shí)現(xiàn)的呢?本文就帶著大家去Linux進(jìn)程間通信一探究竟,找出他們的原理。

概念

我們都知道,應(yīng)用程序在運(yùn)行起來(lái)之后(進(jìn)程),是相互獨(dú)立的,都有自己的進(jìn)程地址空間。但是往往在一些業(yè)務(wù)上需要進(jìn)程間的通信,來(lái)完成系統(tǒng)的某個(gè)完整的功能。我們來(lái)看下進(jìn)程間通信能干那些事情?首先當(dāng)然最重要的是:

  1. 數(shù)據(jù)傳輸。一個(gè)進(jìn)程需要發(fā)送數(shù)據(jù)到另一個(gè)進(jìn)程,這種需求肯定是存在的。

  2. 共享數(shù)據(jù)。如果有多個(gè)進(jìn)程想要訪問(wèn)數(shù)據(jù),一個(gè)進(jìn)程修改了內(nèi)容,另一個(gè)進(jìn)程能夠立即看到內(nèi)容變化。

  3. 資源保護(hù):上面的的操作中存在競(jìng)爭(zhēng)情況,內(nèi)核需要提供鎖和同步機(jī)制。

  4. 通知:一個(gè)進(jìn)程需要向另一個(gè)進(jìn)程發(fā)送消息,通知發(fā)生了某個(gè)事件。

  5. 控制:有些進(jìn)程需要控制另一個(gè)進(jìn)程的運(yùn)行。典型的例子就是gdb,可參考之前文章【gdb到底是怎么實(shí)現(xiàn)的?

通信方式

進(jìn)程間的通信方式一般可以分為八種,如下:

他們?cè)诓煌臉?biāo)準(zhǔn)都有不同的實(shí)現(xiàn),如下圖所示:

我們先從管道開(kāi)始講起來(lái)吧。

管道

這里說(shuō)的管理特指的是無(wú)名管道,它是一種半雙工的通信方式。也就是說(shuō)數(shù)據(jù)只能單向流動(dòng),一般是在具有親緣關(guān)系的進(jìn)程間使用,比如父子進(jìn)程。當(dāng)一個(gè)進(jìn)程創(chuàng)建了一個(gè)管道,并調(diào)用fork創(chuàng)建自己的一個(gè)子進(jìn)程后,父進(jìn)程關(guān)閉讀管道端,子進(jìn)程關(guān)閉寫(xiě)管道端,這樣提供了兩個(gè)進(jìn)程之間數(shù)據(jù)流動(dòng)的一種方式。

管道是怎么通信的呢?

首先管道是內(nèi)核的一個(gè)緩沖區(qū),而且是在內(nèi)存中。管道一頭連接著一個(gè)進(jìn)程的輸出,另一頭連接著另一個(gè)進(jìn)程的輸入。一個(gè)緩沖區(qū)不需要很大,它被設(shè)計(jì)成為環(huán)形的數(shù)據(jù)結(jié)構(gòu),以便管道可以被循環(huán)利用。當(dāng)管道中沒(méi)有信息的話,從管道中讀取的進(jìn)程會(huì)等待,直到另一端的進(jìn)程放入信息。當(dāng)管道被放滿信息的時(shí)候,嘗試放入信息的進(jìn)程會(huì)等待,直到另一端的進(jìn)程取出信息。當(dāng)兩個(gè)進(jìn)程都終結(jié)的時(shí)候,管道也自動(dòng)消失。看下圖:

那管道怎樣建立的呢?

從原理上,管道利用fork機(jī)制建立,從而讓兩個(gè)進(jìn)程可以連接到同一個(gè)PIPE上。最開(kāi)始的時(shí)候,上面的兩個(gè)箭頭都連接在同一個(gè)進(jìn)程1上(連接在進(jìn)程1上的兩個(gè)箭頭),如下圖。當(dāng)fork復(fù)制進(jìn)程的時(shí)候,會(huì)將這兩個(gè)連接也復(fù)制到新的進(jìn)程(進(jìn)程2)。隨后,每個(gè)進(jìn)程關(guān)閉自己不需要的一個(gè)連接 (兩個(gè)黑色的箭頭被關(guān)閉; 進(jìn)程1關(guān)閉從PIPE來(lái)的輸入連接,進(jìn)程2關(guān)閉輸出到PIPE的連接),這樣,剩下的紅色連接就構(gòu)成了如上圖的PIPE。

管道在內(nèi)核中具體怎么實(shí)現(xiàn)的呢?

在Linux內(nèi)核中,并沒(méi)有針對(duì)管道新增數(shù)據(jù)結(jié)構(gòu)。而是巧妙的借用了文件系統(tǒng)的file結(jié)構(gòu)和虛擬文件系統(tǒng)的索引節(jié)點(diǎn)inode。通過(guò)將兩個(gè) file 結(jié)構(gòu)指向同一個(gè)臨時(shí)的 VFS 索引節(jié)點(diǎn),而這個(gè) VFS 索引節(jié)點(diǎn)又指向一個(gè)物理頁(yè)面而實(shí)現(xiàn)的。

具體實(shí)現(xiàn)

管道的實(shí)現(xiàn)其實(shí)也不難,源代碼在內(nèi)核工程中的fs/pipe.c,我們著重的講兩個(gè)比較重要的接口吧,也就是常用的pipe_read()和pipe_write(),前者是管道讀函數(shù),后者是管道寫(xiě)函數(shù)。

管道寫(xiě)函數(shù)將字節(jié)數(shù)據(jù)復(fù)制到虛擬文件系統(tǒng)索引節(jié)點(diǎn)指向的物理內(nèi)存頁(yè),而讀函數(shù)則是相反:讀出數(shù)據(jù)。當(dāng)然這里存在著競(jìng)爭(zhēng)的管理,需要一定的同步機(jī)制,使用鎖,等待隊(duì)列和信號(hào)。

當(dāng)我們寫(xiě)的時(shí)候,調(diào)用write(),內(nèi)核根據(jù)傳入的文件描述符fd,找到該文件的file結(jié)構(gòu)。然后執(zhí)行結(jié)構(gòu)中f_op中的寫(xiě)函數(shù)。寫(xiě)函數(shù)在向內(nèi)存寫(xiě)入數(shù)據(jù)之前,必須首先檢查虛擬文件系統(tǒng)索引節(jié)點(diǎn)信息,檢查是否有足夠的內(nèi)存空間可以寫(xiě)和內(nèi)存沒(méi)有被讀程序鎖定這兩個(gè)條件,只有滿足了,才真正的進(jìn)行內(nèi)存拷貝。

接下來(lái)寫(xiě)函數(shù)就會(huì)鎖定內(nèi)存,然后復(fù)制數(shù)據(jù)到內(nèi)存,否則就在虛擬文件系統(tǒng)inode的等待隊(duì)列中。

管道的讀取過(guò)程和寫(xiě)入過(guò)程類似。但是,進(jìn)程可以在沒(méi)有數(shù)據(jù)或內(nèi)存被鎖定時(shí)立即返回錯(cuò)誤信息,而不是阻塞該進(jìn)程,這依賴于文件或管道的打開(kāi)模式。反之,進(jìn)程可以休眠在索引節(jié)點(diǎn)的等待隊(duì)列中等待寫(xiě)入進(jìn)程寫(xiě)入數(shù)據(jù)。當(dāng)所有的進(jìn)程完成了管道操作之后,管道的索引節(jié)點(diǎn)被丟棄,而共享數(shù)據(jù)頁(yè)也被釋放。

總結(jié)

由于篇幅的限制,八大進(jìn)程間通信只講了管道,文章開(kāi)頭的疑問(wèn)也只能等到后續(xù)文章了,也算是留個(gè)懸念吧。未完待續(xù)....

覺(jué)得不錯(cuò),記得點(diǎn)贊轉(zhuǎn)發(fā),關(guān)注我!

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多