1. 程式人生 > 實用技巧 >八、網路服務I/O模型

八、網路服務I/O模型

8.1、四種的I/O模型

在作業系統中,程序無法直接操作I/O裝置,其必須通過系統呼叫請求kernel來協助完成I/O動作,而核心會為每個I/O裝置維護一個buffer。程序與I/O之間的通訊模型如圖所示。

wKioL1k0wdSTU6hjAAA1yd6YWqA094.png

對於輸入而言,等待(wait)資料輸入至buffer需要時間,而從buffer複製(copy)資料至程序也需要時間。根據呼叫者與被呼叫者的不同就有四種I/0模型。

呼叫者處理措施:
阻塞:程序發起I/O呼叫, 未完成之前,當前程序會被掛起;

非阻塞:程序發起I/O呼叫,被呼叫函式完成之前不會阻塞當前程序,而是立即返回;

被呼叫者響應:

同步:程序發起一個過程呼叫(功能、函式)呼叫後,在沒得到結果之前,該呼叫將不會返回;
非同步:程序發起一個過程呼叫後,即使呼叫者不能立即得結果,但呼叫卻會返回,返回是未未完成 狀態;當呼叫完成後,核心會自行通知呼叫者結果已經OK;

wKiom1k0wn3Bxg-9AAAPTIjCpmg344.png-wh_50

8.2、五種網路服務I/0模型

根據等待模式不同,I/O動作可分為五種模式:

同步阻塞程序會一直阻塞,直到資料拷貝完成

wKiom1k0wuCwKQS0AAFEJe5A8yk967.png-wh_50

同步非阻塞非阻塞IO通過程序反覆呼叫IO函式(多次系統呼叫,並馬上返回);在資料拷貝的過程中,程序是阻塞的

wKioL1k0wx3AdIkRAAIZSFxvqbw397.png-wh_50

I/O 複用:主要是select和epoll;對一個IO埠,兩次呼叫,兩次返回,比阻塞IO並沒有什麼優越性;關鍵是能實現同時對多個IO埠進行監聽。

wKiom1k0wx7g6OTYAAH3Am-OY0U161.png-wh_50

非同步IO:資料拷貝的時候程序無需阻塞。

wKioL1k0wx7wiapjAAFyv-G9x64829.png-wh_50

訊號驅動:兩次呼叫,兩次返回。

wKiom1k0wx_TkIZJAAHKmSujLKo270.png-wh_50

五種IO模型的比較:

wKioL1k0wx-BxJd8AAJfyslDNx8650.png-wh_50

8.3、select/poll/epoll

select

本質上是通過設定或者檢查存放fd標誌位的資料結構來進行下一步處理,但是單個程序可監視的fd數量被限制,即能監聽埠的大小有限。對socket進行掃描時是線性掃描,即採用輪詢的方法,效率較低,需要維護一個用來存放大量fd的資料結構,這樣會使得使用者空間和核心空間在傳遞該結構時複製開銷大。

#cat/proc/sys/fs/file-max#檢視可監聽fd的數量

poll

本質上和select沒有區別,它將使用者傳入的陣列拷貝到核心空間,然後查詢每個fd對應的裝置狀態,其沒有最大連線數的限制,原因是它是基於連結串列來儲存的,但是同樣有一個缺點:大量的fd的陣列被整體複製於使用者態和核心地址空間之間,而不管這樣的複製是不是有意。 poll還有一個特點是“水平觸發”,如果報告了fd後,沒有被處理,那麼下次poll時會再次報告該fd。

epoll

支援水平觸發和邊緣觸發,最大的特點在於邊緣觸發,它只告訴程序哪些fd剛剛變為就需態,並且只會通知一次。 使用“事件”的就緒通知方式,通過epoll_ctl註冊fd,一旦該fd就緒,核心就會採用類似callback的回撥機制來啟用該fd,epoll_wait便可以收到通知。

其優點是沒有最大併發連線的限制:能開啟的FD的上限遠大於1024(1G的記憶體上能監聽約10萬個埠)效率提升:非輪詢的方式,不會隨著FD數目的增加而效率下降;只有活躍可用的FD才會呼叫callback函式,即epoll最大的優點就在於它只管理“活躍”的連線,而跟連線總數無關。使用記憶體拷貝方式,利用mmap()檔案對映記憶體加速與核心空間的訊息傳遞;即epoll使用mmap減少複製開銷。



轉載於:https://blog.51cto.com/yinsuifeng/1932187