一個故事看懂程式間通訊技術

軒轅之風發表於2021-07-30

月黑風高夜,突然聽得咣噹一聲,Web伺服器的目錄下冒出了兩個檔案,弄出了不小的聲響。這兩個傢伙一胖一瘦,鬼鬼祟祟,潛入這臺計算機,不知要搞什麼名堂。

“二弟,一會兒我們們按照計劃好的執行起來,分頭行事,你等我訊號,拿到資料後趕緊撤”,胖子對瘦子說到。

“老大,這地方我不熟悉,我怎麼等你訊號?我們們得想個聯絡方式,一會兒通訊使用”,瘦子說到。

“這個不用擔心,主人都交代好了”,胖子一邊說,一邊從背後拿出一本 《Linux程式間通訊手冊》 翻了起來。

訊號

翻開手冊的第一頁,上面寫著:訊號——Signal,兩個傢伙開始認真研究起來。

片刻之後,胖子程式說道:“唉,這個不行,往後翻吧!”

瘦子程式不解,問道:“咋就不行啦?”

“你看這裡,手冊上說了,訊號是Linux上的一種軟中斷通訊機制,可以向指定程式傳送通知,總共有64種訊號,不過這個訊號只能作為通知使用,沒辦法傳輸資料”

“沒法傳輸資料?那這玩意有什麼用?”

“還是有用啊,可以通知某個程式發生了什麼事件,比如kill命令就是利用這個訊號來告知程式退出從而實現殺程式的效果的”

“原來如此”,瘦子程式若有所思的點了點頭,此時胖子已經翻到了手冊的第二頁。

socket

“你看,手冊上寫了,可以用socket”,胖子說到。

“socket?那不是網路通訊使用的嗎?”,瘦子有些疑惑。

“是啊,不過我們們一樣可以用來在本地計算機通訊,把連線的IP地址換成127.0.0.1就行了”

“感覺有點太招搖了,我們們計算機內部程式通訊,資料還要經過網路卡,很容易被發現的!”

“不會不會,手冊上說了,127.0.0.1是本地迴環地址,資料在協議棧就進行轉發了,根本不會到達網路卡”

 

 

“那抓包能抓到我們們通訊嗎?”

“嗯,讓我看看···手冊上說,可以在虛擬的迴環網路卡lo上抓到資料”

“還是算了吧,我們幹這事得悄悄進行,不能留下痕跡,你再看看還有沒有別的招”

聽瘦子這麼一說,胖子倒也覺得有理,便在手冊上繼續翻了起來。

匿名管道

“哎,有了有了,這個叫匿名管道的,聽起來就比較隱祕,應該不會被發現。”

瘦子接過手冊,看了起來。

這倆盯著手冊上的兩個圖研究了半天,總算弄明白了,所謂匿名管道不過是核心中的一段緩衝區,提供了讀寫兩個口子,通過fork建立子程式後,子程式繼承了父程式的管道資訊,兩邊只要約定好,一個讀,一個寫,就能實現通訊了。

 

 

 

 

“老大,這匿名管道是單向的,我們們要通訊,得整兩根管道才行,一個你寫我讀,一個我寫你讀”

“看起來挺靠譜,就這麼幹!”,二人達成了一致。

胖子程式率先執行起來,隨後建立了兩個管道,一個用來傳送訊息,一個用來接收訊息。接著執行fork,將瘦子程式也執行了起來。

 

 

時間過的很快,轉眼已是深夜,隨著計算機被關掉,兩個傢伙的程式也都退出了。

半夜無人之際,硬碟中這兩個傢伙開始吵起來了。

“你是怎麼回事?我給你發訊息怎麼也不回,害得我一連發了一堆訊息,最後把管道塞滿了,我都阻塞了!”,胖子程式氣憤地說道。

“嗨!別提了,主人給我寫的程式有bug,今天執行的時候不小心崩潰了,等我再次起來時,發現管道不見了,什麼情況啊?”,瘦子程式說完嘆了一口氣。

“那肯定不行,這匿名管道需要有親緣關係的程式繼承後才能通訊,你用別的方式執行起來,肯定看不到我建立的管道啊!”

“這匿名管道用起來太麻煩了,看看還有沒有別的通訊方式?”

胖子程式又掏出了手冊,翻了起來。

訊息佇列

“有了有了,這裡還寫了兩種方式:命名管道、訊息佇列”,胖子程式說到。

“命名管道?跟匿名管道有什麼區別嗎?”

“命名管道有名字,有了名字就不限有親緣關係的程式才能通訊了,只要使用這個名字,都能開啟管道通訊,這下你就算掛了重啟也能跟我聯絡上了”

“那訊息佇列又是什麼東西?”

“額,讓我看一下”

“給我也看看”,瘦子程式湊了上去,一起看了起來。

 

 

過了一會兒,瘦子程式說道:“我看明白了,這訊息佇列是核心中的一個訊息連結串列,按照訊息塊組織,比那管道全是二進位制資料流堆積在一起好用多了”

“有道理,而且這訊息還可以指定型別,這樣我們們倆就不用弄兩個管道,一個訊息佇列就行了,我們們倆使用不同的訊息型別,可省了不少事兒啊!”

“那我們們就用訊息佇列吧,別用那什麼管道了”

“好,就這麼幹!”

兩個傢伙一拍即合,準備第二天再大幹一場。

第二天,計算機啟動後,它們又偷偷的執行了起來。

這一次用上了訊息佇列,聯絡起來方便了不少。

共享記憶體

不知過了多久,那瘦子程式總算來信兒了,胖子從訊息佇列中取出一看,只見上面寫著:

“老大,我拿到了資料了,需要你來處理一下,不過這資料體量有點大,用管道和訊息佇列傳輸效率都太低了,有無辦法快速把資料傳送給你,盼速回。”

胖子程式心裡一陣歡喜,資料拿到了,總算可以回去交差了。不過怎麼樣快速把資料傳送過來呢,心裡又犯起了嘀咕。

此時,胖子程式又一次拿出手冊,翻到了最後一頁,發現了一個叫“共享記憶體”的東西,彷彿像抓住了救命稻草一般,仔細研究了起來。

片刻之後,胖子的臉上露出了笑容,隨後寫下了一條訊息給瘦子程式傳送了過去。

卻說這瘦子程式正在焦急等待訊息中,收到老大的回信後,趕緊取出來看:

二弟,主人的手冊中提到,可以使用共享記憶體進行程式間通訊。

我準備了幾個記憶體頁面,你將它們對映到你的程式地址空間中,我們們就能共享這一片記憶體,你寫的資料我能立即看到,我寫的你也能立即看到,雖然我們們各自讀寫的地址不同,但實際上是訪問的同一片實體記憶體頁面,比管道和訊息佇列效率高多了!

不過為了防止我們們一起讀寫發生衝突,需要配合訊號量一起使用,用它來實現程式間同步。

具體的使用方法如下:

······

······

盼速回!

瘦子程式看完,心中大喜!趕緊通過訊息佇列發了一封回信。

隨後,通過老大交代的方法開始操作起來,開啟共享、對映掛載一氣呵成。再接著,將資料一股腦兒寫到了共享的記憶體頁面中。

大功告成之後,便退出了程式,按照計劃準備撤退,卻不見了胖子的蹤跡,既無程式也無檔案。

“這傢伙難道拋下我一個人跑了?”

正想著,突然“嗡”的一聲,瘦子的程式檔案也沒了。

卻看那檔案目錄之下,只留了一卷《Linux程式間通訊手冊》···

 

相關推薦

一個故事看懂Redis

一個故事看懂Docker

一個故事看懂CPU中斷技術

相關文章