騰訊面試:進程通信了解么?
本文轉載自微信公眾號「CS指南」,作者大白。轉載本文請聯系CS指南公眾號。
中午
一個陽光明媚的中午,大白來到了領導的辦公室。
大白:領導,從昨天晚上開始,我牙特別疼,我感覺我得去一趟醫(yī)院...
領導:好的,你快去吧哈,最近注意身體...
當日下午
騰訊大樓,某會議室內~
大白:面試官您好,我是大白!我雖然剛工作不到一年,但是我有強悍的編程基本功以及有豐富的項目經驗......
面試官:行,我大概了解了,接下來我問你點八股...不是,我們好好探討一些底層原理。
大白:(內心:沒問題,我就擅長這個,你沒看過我的八股文騷套路系列嗎?)好的,面試官!
面試官:先問個簡單的,你講下進程與線程的區(qū)別吧!
大白:好的,一個進程里可以包含很多線程!
面試官:沒了?
大白:沒了呀。
面試官:我對你的面試差不多了,你回去等結...
面試正式開始
大白:別別別,開個玩笑。其實兩者區(qū)別還挺大的,先從進程講起,我之前就寫過一篇講 Linux 進程創(chuàng)建 的文章...
面試官:打斷一下,你那篇文章我看過,寫的還不錯。我問點你在文章里沒提到的。你了解進程通信嗎?
大白:了解呀,主要有以下幾種進程通信方式:管道、消息隊列、共享內存、信號量、Socket。
面試官:那你平常用過管道的方式進行進程通信嗎?
大白:用過呀,經常用。管道有匿名管道和命名管道兩種。我下面給您詳細介紹下。
先舉個例子吧,下面這條 linux 命令就運用了管道。
- echo "I'm dabai" | tee a.out
上面這條命令的具體功能是在 Linux 控制臺輸出 “ I’m dabai”,并且將輸出的信息作為輸入傳遞到 a.out 文件中??梢钥闯?I 的左邊是輸入,右邊是輸出。“|”代表的管道隨著命令創(chuàng)建,命令執(zhí)行完成后也會自動銷毀.
另外一種方式就是通過 mkfifo 顯示創(chuàng)建命名管道。
- mkfifo dabaipipe
上述命令就創(chuàng)建了一個名叫 “dabaipipe" 的管道。我們可以向管道中寫入信息,比如:
- echo "hello ! I'm dabai" > dabaipipie
想要讀取管道中的信息,采用下面的命令就可以啦!
- cat < dabaipipe
- #輸出 hello ! I'm dabai
面試官:呦!還不錯,那我問你什么時候該用匿名管道,什么時候該用命名管道。
大白:其實這要從匿名管道的缺點說起。匿名管道有兩個缺點,這既是他的缺點也是他的特點。
(1)匿名管道僅支持父進程和子進程間的通信。
(2)匿名管道不支持跨網絡的兩個進程之間的通信
也正是因為這兩個特點,匿名管道所需要的系統開銷比命名管道小很多。(匿名管道中的文件不會寫到磁盤上,而命名管道中的文件會寫到磁盤上)
所以什么時候該用匿名管道,什么時候該用命名管道就很顯而易見了。(快夸我)
面試官:等等,你說啥?你說匿名管道僅僅支持父進程和子進程間的通信?那你剛才這條命令 “echo "I'm dabai" | tee a.out”,誰是誰的子進程?
大白:(內心:這面試官果然不講武德!幸虧我早有準備,就等著你跳坑了,就這個點我能給你講到面試結束)
是這樣的,匿名管道的創(chuàng)建過程很有意思,我給您講一下,這樣就能解答您剛才的問題。
如果要創(chuàng)建匿名管道,我們需要接下來的幾步。
1.我們需要創(chuàng)建匿名管道的"管子",其實就是內核中的一段緩存。
2.為了通信,我們需要創(chuàng)建一個進程,然后在進程中會創(chuàng)建兩個文件描述符指向管道的兩端(一個指向輸入端,一個指向輸出端)。
這個時候,我們的匿名管道就變成下面這個樣子了。進程想要向管道中輸入數據那么就通過輸入端描述符進行寫入操作,想要從管道中取數據就通過輸出端描述符進行讀取操作。
從上面的圖我們也可以看出,根本沒有實現進程間通信。那么怎樣實現父進程和子進程通信呢?我那篇講進程的文章中講過父進程創(chuàng)建子進程是怎么創(chuàng)建的,大家還記得嗎?就是要用 fork。父進程通過 fork 創(chuàng)建子進程,子進程會把父進程的代碼復制一份,這樣父進程的輸入端描述符子進程也復制到了。這個時候父進程和子進程都會同時指向管道。
我們再將子進程的輸入關閉,父進程的輸出關閉,就可以啦!
至于”echo "I'm dabai" | tee a.out “ 這條命令, | 兩邊并不是父子進程,那他們是怎么完成進程通信的。其實,這兩個進程都是通過 shell 進程 fork 出來的。然后兩個進程分別就連接到管道的輸入和輸出端了。再把多余的輸入和輸出關閉就可以啦。
最后匿名管道的結構圖我就不用畫了吧?(內心:這面試都一個多小時了,我還回公司蹭免費晚餐和九點下班打車呢)
面試官:要不你還是畫一下吧!
大白:那好吧...就是下面這個樣子!(內心:你就不急著去吃飯嗎?)
面試官:小伙子可以呀,我對你挺滿意的,我給你過了。本來還想詳細問問你進程通信的其它幾種方式,但是我得下班了。你等等下一面的面試官約你面試時間吧!
和面試官加了微信后??戳丝磿r間,還行,還能回趟公司把餐補領了再回家,又是充實的一天。最近把進程通信其他幾種方式學一學給下一面面試官講。
參考資料:
極客時間《趣談 Linux 操作系統》 鏈接:http://gk.link/a/10zn1
《Linux系統編程、網絡編程》第7章 進程間通信(本機IPC) 鏈接:https://www.bilibili.com/video/BV1fE411v7Bb
JavaGuide 操作系統篇 鏈接:https://snailclimb.gitee.io/javaguide/#/docs/cs-basics/operating-system/basis