作業系統I/O模型及輪詢技術演變

五月君發表於2019-04-20

本來是想要介紹Node.js的輪詢技術,但是在這之前先了解下作業系統I/O模式的演進,有助於之後的一些理解,作業系統對於I/O的處理通常是有兩步

  • 應用程式先發起系統呼叫待資料就緒
  • 將資料從核心緩衝區拷貝到應用緩衝區

Github技術部落格: Node.js技術棧

快速導航

面試指南

  • I/O複用輪詢技術select和epoll的區別?,參考:#

同步阻塞IO

從應用程式開始系統呼叫->資料就緒,進行拷貝->拷貝結束,這之間應用程式都處於等待狀態,不能做其它事情,直到將資料拷貝到使用者空間或出錯才返回,我們稱之為阻塞I/O模式。

圖片描述

同步非阻塞IO

相比於同步阻塞I/O模式,同步非阻塞I/O在每次呼叫之後,如果資料沒有就緒就會立即返回,之後重複呼叫來檢查I/O操作是否就緒,這對CPU資源是一個極其浪費的操作,直到資料就緒將資料從核心拷貝到使用者空間,返回成功指示給到應用程式。

Read:就是一種實現,通過重複輪詢I/O來判斷。

圖片描述

IO多路複用

連結(Socket)併發大的情況,上面兩種就不適合了,前面一個處理不完,後面就只能乾等,這裡就用到了I/O多路複用,下圖所示相比較前兩種,分為了兩步,先進行select資料就緒後,在呼叫recvfrom進行真正的I/O讀寫操作。它的高階之處還在於能夠一個執行緒同時處理多個Socket。

圖片描述

I/O多路服用有多種實現模式:selectpollepollkqueue

  • select

通過輪詢檢查在檔案描述符上設定的標識位來進行判斷,Select的輪詢相當於在資料庫中查詢一條記錄沒有建立索引,對所有的Socket進行全部遍歷,這對CPU是浪費的。另外Select還有一個限制,對於單個程式所能開啟的檔案描述符最大隻能是1024,那麼基於Select的輪詢技術最多也只能很好的處理1000併發的吞吐量,可以檢視上一個10年,著名的C10K併發連線問題

  • poll

poll和select在實現上沒有本質的區別,相比較select,poll基於連結串列來實現,沒有了最大連結1024的限制。但是當檔案描述符多了之後,每次呼叫都會對連結進行線性遍歷,效能還是十分低下的。

  • epoll

是linux下效率最高的I/O事件通知機制,沒有最大連結限制,通過callbak回撥通知機制,不在是每次呼叫都對連結進行線性遍歷,這樣就不會隨著檔案描述符的增加導致效率下降。

在1GB記憶體的機器上能監聽大約10萬個埠,遠超過select的1024限制,具體可以在伺服器上檢視cat /proc/sys/fs/file-max

  • kqueue

與epoll類似,僅存於FreeBSD(一種類UNIX作業系統)。

訊號驅動IO

僅在Unix上支援,與I/O多路複用相比避免了select的阻塞輪詢。應用程式進行系統呼叫後立即返回,處理其它事物,在資料就緒之後系統會傳送一個SIGIO訊號到應用程式,應用程式開始讀取資料。

圖片描述

非同步IO模型

非同步I/O模型是目前最理想的一種形式,應用程式發起系統呼叫後無需等待直接返回當前呼叫狀態,進行後續的其它任務,結果由核心完成I/O操作之後通過回撥通知到我們的應用程式,中間沒有阻塞過程。

在Linux2.6之後增加了非同步I/O的實現方式 AIO,但是很少系統能夠實現。

圖片描述

select和epoll的區別

如果問到輪詢技術的實現一般也會考察select和epoll的區別

  • 在操作方式上select採用了線性遍歷來查詢,連結多了之後可以想象一下在一個諾大的陣列中每次通過遍歷來鎖定一個連結,是多麼的消耗效能。epoll則不需要遍歷,採用的是回撥機制,可以看作一個HashTable,來鎖定一個物件是很快的。對於檔案描述符(最大連線數)select限制為1024,epoll則沒有這個限制,通常在1G記憶體的機器上所能支援的連線數為10W左右。
  • 作業系統支援上來看,目前流行的高效能Web伺服器Nginx是基於epoll來實現高併發,當然如果你的連結很小的情況下區別還是不大的select也能滿足,如果是大流量、高併發情況epoll目前還是首選模型。

白話風格

白話風格(小明與妹子的邂逅)講解作業系統I/O模型及輪詢技術演變

故事標題:小明與妹子的邂逅
情節介紹:小明在校園一次文藝晚會上邂逅了一位妹子,在只得知妹子名字、手機號的情況下,經過幾天的苦苦追尋,歷經千山萬水,終得美人歸!
演員介紹:男一號@小明、女一號@妹子、串場@門衛大爺

  1. 同步阻塞I/O模式

小明電話相約妹子在校門口,然後小明很專一、不見到妹子不回家,期間沒有做任何事情,一直在等待!

  1. 同步非阻塞I/O模式

小明電話相約妹子在校門口,妹子還沒準備好(出門前化妝幾小時。。。),這時候的小明很執著,每隔一會兒給妹子發個資訊直到妹子準備好了。

  1. I/O多路複用模式

    1. select 小明電話相約妹子在校門口,委託門衛select大爺幫忙,select大爺很敬業每出去一個人都會進行詢問,但是select大爺有個限制最多隻能詢問1024個。
    2. poll poll類似於select功能,不同的是poll大爺沒有1024限制,可以一直堅持,但是當poll大爺超過1024,詢問的越來越多之後就顯得越來越精疲力盡了。
    3. epoll 小明電話相約妹子在校門口,委託門衛epoll大爺幫忙,epoll大爺不在是每個詢問,規定每個人出入校門必須帶上學生證,這樣opoll大爺就是知道哪個是小明的女神了,epoll大爺找到女神之後在電話通知小明。
  2. 訊號驅動I/O模式

小明電話相約妹子在校門口,此時妹子回覆說我還沒準備好(出門前化妝幾小時。。。),這個時候小明也沒去,而是先去幹其它事情了,等妹子準備好之後電話通知小明,我已經準備好了,小明這個時候才去校門口等著和妹子的約會。

  1. 非同步I/O模式

小明告訴妹子我們在校園門口相約,之後小明沒有在那乾等了,而是先回宿舍休息會或者和朋友在打會球等等,妹子到校門口之後電話通知小明,我已經來啦。

下一節Node.js中的EventLoop

作者:五月君
連結:www.imooc.com/article/285…
來源:慕課網
Github: Node.js技術棧

參考指南

相關文章