1. 程式人生 > >那些年讓人迷惑的同步、非同步、阻塞、非阻塞

那些年讓人迷惑的同步、非同步、阻塞、非阻塞

在IT圈混飯吃,不管你用什麼程式語言、從事前端還是後端,阻塞、非阻塞、非同步、同步這些概念,都需要清晰地掌握,否則,怎麼與面試官談笑風生(chui niu pi)?但是,掌握這些概念又不是非常容易,尤其對非科班出身的,更加困難。本文試圖給出一個清晰簡明但不失深刻的介紹,希望對大家有所幫助。

1、從I/O說起

這些概念之所以容易令人迷惑,在於很多人對I/O就沒有清晰準確的理解,後面的理解自然不可能正確。我想用一個具體的例子來說明一下I/O。

設想自己是一個程序,就叫小進吧。小進需要接收一個輸入,我們不管這個輸入是從網路套接字來,還是鍵盤,滑鼠來,輸入的來源可以千千萬萬。但是,都必須由核心來幫小進完成,為啥核心這麼霸道?因為計算機上執行的可不只是咱小進一個程序,還有很多程序。這些程序兄弟也可能需要從這些輸入裝置接收輸入,沒有核心居中協調,豈不是亂套。

從小進的角度看,核心幫助它完成輸入,其實包括三個步驟:

  • 1、核心替小進接收好資料,這些資料暫時存在核心的記憶體空間
  • 2、核心將資料從自己的記憶體空間複製到小進的記憶體空間
  • 3、告訴小進,輸入資料來了,趕快讀吧

這三步看似挺簡單,其實在具體實現時,有很多地方需要考慮:

  • 0、小進如何告訴核心自己要接收一個輸入?
  • 1、核心接到小進的請求,替小進接收好資料這段時間, 小進咋辦?
  • 2、核心在將資料複製到小進的記憶體空間這段時間,小進咋辦?
  • 3、到底什麼時候告訴小進資料準備好了,是在核心接收好資料之後就告訴小進,還是在將資料複製到小進的記憶體空間之後再告訴他?
  • 4、核心以什麼樣的方式告訴小進,資料準備好了?

2、阻塞式I/O模型

對上面5個問題,最簡單的解決方案就是阻塞式I/O模型,它的過程是這樣的:

小進:核心核心,我要接收一個鍵盤輸入,快點幫我完成!

核心:好咧!biubiu!一個阻塞丟給小進,小進頓時石化,就像被孫悟空點了定一樣。

就這樣,小進在石化中,時間一點點流逝。終於,核心收到了資料。

核心:資料終於來了,我要開幹了!duang duang duang,先把資料存在自己的核心空間,然後又複製到小進的使用者空間。

核心:biubiu!一個解除阻塞丟給小進,小進瞬間復活,小進的記憶還是停留在讓核心幫他接收輸入時。

小進:哇!核心真靠譜,資料已經有了!幹活去!

我們可以看到,小進發出接收輸入的請求給核心開始,就處於阻塞狀態,直到核心將資料複製到小進的使用者空間,小進才解除阻塞。

3、非阻塞式I/O

小進發現,阻塞式I/O中,自己總要被阻塞好久,好不爽啊,於是小進改用了非阻塞式I/O,其過程是這樣的:

小進:核心核心,我要接收一個輸入,趕緊幫我看看,資料到了沒有,先說好,不要阻塞我。

核心:查看了一下自己的核心空間,沒有發現數據,於是迅速告訴小進,沒有呢!並繼續幫小進等著資料。

如此這樣,小進不斷地問核心,終於,過了一段時間,小進再一次詢問時,核心往自己的空間中一查,呦!資料來了,不勝其煩的核心迅速告訴小進,資料好了!

小進:快給我!

核心:biu!一個阻塞丟給小進,悲催的小進還是石化了!

核心趕緊將自己空間的輸入資料複製到小進的使用者空間,複製好後。

核心:biu!一個非阻塞丟給小進,小進立馬復活

小進:哇!資料來了,啥也不說,幹活!

我們看到,所謂的非阻塞I/O,其實在核心將資料從核心空間複製到小進的使用者空間時,小進還是被阻塞的。

4、訊號驅動式I/O

非阻塞I/O中,小進不停地問核心,資料好了沒有啊,核心感覺太煩了,於是想出一個好辦法。

核心告訴小進,本核心升級了,如果想要我替你接收輸入,請先註冊一個訊號處理函式,等資料準備好時,我會發訊號給你。於是,現在的流程是這樣的:

小進:註冊訊號處理函式,告訴核心,自己要接收一個輸入,然後繼續幹活!

核心:收到函式,開始執行資料接收

接收完成時,給小進發送訊號,訊號處理函式收到訊號,開始向核心傳送讀資料請求

核心:biu!阻塞了小進,並把資料從核心空間複製到小進的使用者空間。

核心:biu!解除了阻塞

小進:哇!資料來了!啥也不說,幹活去!

5、非同步I/O

上面的三種I/O解決方案中,小進都被阻塞了,只不過是阻塞時間長短不一樣,第一種方案中小進被阻塞的時間長一些,在核心接收資料以及將資料複製到小進的使用者空間時,都被阻塞。

第二、第三種方案中,只在核心將資料從核心空間複製到小進的使用者空間時,小進才被阻塞。

我們現在說的非同步I/O,目的就是讓小進絕對不被阻塞。其過程是這樣的:

小進:核心核心,我要接收一個輸入,弄好了告訴我。同時將一個訊號和訊號處理函式告訴核心,然後繼續幹自己的活了。

核心:得了您嘞,您先忙。

一直到核心接收到資料並將資料從核心空間複製到小進的使用者空間後,核心才給小進發送訊號。小進在訊號處理函式中可以直接處理資料。

6、那啥是同步呢?

一句話,凡是讓小進阻塞(不管長短)的I/O方案都是同步I/O。也就是說,阻塞、非阻塞、訊號驅動式都是同步I/O。

7、無總結,不進步

上面,我們從完成輸入時,程序與核心的互動方式的角度分析了不同的I/O解決方案,在這個過程中,解釋清楚了阻塞、非阻塞、同步、非同步的概念。

作者:milter
連結:
https://www.jianshu.com/p/3d603166f54d


掃碼關注有驚喜

(轉載本站文章請註明作者和出處 方誌朋的部落格