天天看點

詳解 | 求你别用效率低下的I/O了,要不試試這種I/O

HI!我是小小,我們又見面了,今天是國慶假期的最後一天,在這最後一天,舉國同慶的時刻。。。。我們一塊來學習IO,這一次,學習 NIO,BIO,AIO等各種IO

Linux 基礎知識回顧

使用者空間和核心空間

現在的作業系統都采用虛拟尋址,處理器先産生一個虛拟位址,然後通過位址翻譯成為實體位址,再通過總線的傳遞,最後處理器拿到某個實體位址傳回的位元組。對于32位作業系統來說,它的尋址空間,為4G,作業系統的核心是核心,獨立于普通的應用程式,可以通路受保護的記憶體空間,也有通路底層硬體裝置的所有權限,為了保證使用者程序不能直接操作核心,保證核心安全,作業系統把虛拟空間劃分為兩個部分,一部分為核心空間,一部分為使用者空間。對于Linux系統來說,把高直接,1G,給核心使用,稱之為核心空間。把低的3G位元組,送給程序使用,稱之為使用者空間。

直接IO和緩存IO

檔案系統IO分為直接IO和緩存IO。

緩存IO

讀操作

作業系統會檢查核心的緩沖區有沒有需要的資料,如果已經有緩存了,那麼就直接從緩存中傳回,否則會從磁盤中讀取,然後緩存在作業系統的緩存中。

寫操作

把資料從使用者空間複制到核心空間的緩存中,并提示使用者寫操作完成,什麼時候寫入磁盤,由作業系統随機決定。除非強制調用sync指令。舉個栗子,對于write指令來說,資料會先被拷貝進入緩沖區,在拷貝到緩沖區以後才會寫入到裝置中。

詳解 | 求你别用效率低下的I/O了,要不試試這種I/O

直接IO

詳解 | 求你别用效率低下的I/O了,要不試試這種I/O

直接IO相對于緩存IO少了拷貝到應用程序緩沖區這一步

阻塞和同步

這一小節介紹什麼是阻塞,什麼是同步

阻塞和非阻塞

阻塞:往往需要等待緩沖區中的資料準備好過後才處理其他事情,否則一直等待在哪。非阻塞: 當我們的程序通路我們的資料緩沖區的時候,如果資料沒有準備好則直接傳回,當資料讀取完畢以後,會直接觸發,提前監聽好的事件的回調函數。若準備好,也會直接傳回。

同步異步

同步:應用程式要直接參與IO的讀寫操作。異步:所有的IO讀寫交給系統處理,應用程式秩序要等待通知即可,當讀的時候,會調用之前設定好的應用程式的回調函數,當寫的時候,會調用之前設定好的應用程式的回調函數。

常見的IO模型

常見的IO模型有,阻塞IO,非阻塞IO,I/O複用,信号驅動I/O,異步I/O 比較如下圖

詳解 | 求你别用效率低下的I/O了,要不試試這種I/O

以讀取資料為例子 BIO:如果資料源沒有資料會進入阻塞狀态,直到擷取到資料 NIO,如果資料源沒有資料,會直接傳回0,不阻塞。AIO:全稱異步+非阻塞 詳細的見下一節

BIO,NIO,AIO

BIO

詳解 | 求你别用效率低下的I/O了,要不試試這種I/O

同步阻塞IO,伺服器實作模式為一個連接配接一個線程,用戶端有連接配接請求時伺服器就需要啟動一個線程進行處理,後期可以通過線程池的方式提高性能。适用于連接配接數目比較小,固定的架構。

NIO

用戶端發送的連結請求都會注冊到多路複用器上,多路複用器會輪詢到連接配接有IO請求時才啟動一個線程進行處理。NIO方式适用于連接配接數目多,且連接配接比較短的架構,例如聊天伺服器。

IO多路複用模型

IO多路複用,IO就是指我們網絡IO,多路指多個TCP連接配接,複用指複用一個或少量線程,串起來了解就是多個網絡IO複用一個或少量的線程處理這些連接配接。

詳解 | 求你别用效率低下的I/O了,要不試試這種I/O
核心:能處理更多的連結

常用的複用模型,select poll,epoll

select

詳解 | 求你别用效率低下的I/O了,要不試試這種I/O

select 函數監視的檔案描述符分3類,分别是writefds、readfds、和exceptfds。調用後select函數會阻塞,直到有描述符就緒(有資料 可讀、可寫、或者有except),或者逾時(timeout指定等待時間,如果立即傳回設為null即可),函數傳回。當select函數傳回後,可以通過周遊fdset,來找到就緒的描述符。

poll

poll本質上和select沒有差別,它将使用者傳入的數組拷貝到核心空間,然後查詢每個fd對應的裝置狀态,如果裝置就緒則在裝置等待隊列中加入一項并繼續周遊,如果周遊完所有fd後沒有發現就緒裝置,則挂起目前程序,直到裝置就緒或者主動逾時,被喚醒後它又要再次周遊fd。這個過程經曆了多次無謂的周遊。

epoll

epoll支援水準觸發和邊緣觸發,最大的特點在于邊緣觸發,它隻告訴程序哪些fd剛剛變為就緒态,并且隻會通知一次。還有一個特點是,epoll使用“事件”的就緒通知方式,通過epoll_ctl注冊fd,一旦該fd就緒,核心就會采用類似callback的回調機制來激活該fd,epoll_wait便可以收到通知。

比較

詳解 | 求你别用效率低下的I/O了,要不試試這種I/O

應用和架構

Jetty、Mina、Netty、Dubbo、ZooKeeper 之間的通信,都是基于NIO方式實作。常用的架構有Netty

AIO

關于作者

詳解 | 求你别用效率低下的I/O了,要不試試這種I/O

繼續閱讀