IO模型介紹 以及同步異步阻塞非阻塞的區別

 

阻塞:用戶進程訪問數據時,若是未完成IO,等待IO操做完成或者進行系統調用來判斷IO是否完成
非阻塞:用戶進程訪問數據時,會立刻返回一個狀態值,不管是否完成java

同步:用戶進程發起IO(就緒判斷)後,輪詢內核狀態
異步:用戶進程發起IO後,能夠作其餘事情,等待內核通知mysql

 

介紹一下IO模型react

 

網絡IO模型和文件IO模型是同樣的,上圖是IO的5種模型,包括阻塞IO、非阻塞IO、多路複用IO、信號驅動的IO、異步IO。linux

一次IO包括兩個過程,內核數據準備 、把數據從內核空間copy到用戶空間。sql

一、阻塞IO(recvfrom系統調用)是在兩個過程應用都處於阻塞狀態。mongodb

二、非阻塞IO(recvfrom系統調用)是應用發出IO操做後能夠馬上返回,經過輪詢盤判斷數據是否準備好,在copy數據階段阻塞應用。數據庫

三、多路複用IO(select 、recvfrom系統調用)是阻塞調用select,查找可用的套接字,若是有套接字可用,那麼就阻塞調用(recvfrom)完成數據的copy過程。Linux select就是這種模型,缺點是一次select會掃描全部的socket。緩存

四、信號驅動的IO(SIGIO、recvfrom)是應用發出SIG IO後馬上返回,內核中數據準備好後,通知應用,由應用進行阻塞recvfrom調用從內核copy數據。linux epoll就是基於事件的就緒通知方式,省去了全部socket的掃描開銷。網絡

      epoll,kqueue比select高級,select是在內核裏作輪詢操做, epoll是使用回調機制, 消耗的資源更少. 套接字比較多的時候,每次select()都要經過遍歷Socket來完成調度,無論哪一個Socket是活躍的,都遍歷一遍。這會浪費不少CPU時間。epoll給套接字註冊某個回調函數,當他們活躍時,自動完成相關操做,那就避免了輪詢。併發

五、異步IO(aio-read)是應用發出aio-read後立刻返回,數據準備好後,由操做系統把數據copy到應用,並通知應用數據copy完成。

     固然除了以上的IO模式,還有直接IO(應用繞過內核直接訪問磁盤文件),內存映射MMap(創建內存和文件的映射關係),這兩種模式在linux 2.6上本質上沒有差別。

直接IO在數據庫引擎中用的比較多,數據庫的buffer繞過文件系統cache,直接訪問硬盤。MongoDB中就是用到mmap,無需調用read、write系統調用。

 

同步、異步、阻塞、非阻塞通常有這麼幾種組合:

同步非阻塞,典型表明是Java NIO

異步阻塞,典型表明是select,epoll

異步非阻塞,典型表明是aio

 

併發設計中的模式,有如下兩種:

Reactor(NIO)和Preactor(AIO),都是處理派發/分離操做IO事件的。
派發/分離事件就是將單獨的IO事件通知到上層模塊。不一樣之處是,Preactor用於異步,Reactor用於同步。
能夠看出,兩個模式的相同點,都是對某個IO事件的事件通知(即告訴某個模塊,這個IO操做能夠進行或已經完成)。
在結構上,二者也有相同點:dispatch負責提交IO操做(異步)、查詢設備是否可操做(同步),而後當條件知足時,就回調handler。
不一樣點在於,異步狀況下(Preactor),當回調handler時,表示IO操做已經完成;同步狀況下(Reactor),回調handler時,表示
IO設備能夠進行某個操做(can read or can write),handler這個時候開始提交操做。

Reactor和Proactor模式的主要區別就是真正的讀取和寫入操做是有誰來完成的,Reactor中須要應用程序本身讀取或者寫入數據,而Proactor模式中,應用程序不須要進行實際的讀寫過程,它只須要從緩存區讀取或者寫入便可,操做系統會讀取緩存區或者寫入緩存區到真正的IO設備。

相關文章
相關標籤/搜索