簡述同步IO、異步IO、阻塞IO、非阻塞IO之間的聯繫與區別

POSIX

同步IO、異步IO、阻塞IO、非阻塞IO,這幾個詞常見於各類各樣的與網絡相關的文章之中,每每不一樣上下文中它們的意思是不同的,以至於我在很長一段時間對此感到困惑,因此想寫一篇文章整理一下。編程

POSIX(可移植操做系統接口)把同步IO操做定義爲致使進程阻塞直到IO完成的操做,反之則是異步IO

按POSIX的描述彷佛把同步和阻塞劃等號,異步和非阻塞劃等號,可是爲何有的人說同步IO不等於阻塞IO呢?先來講說幾種常見的IO模型吧。網絡

IO模型

這裏統一使用Linux下的系統調用recv做爲例子,它用於從套接字上接收一個消息,由於是一個系統調用,因此調用時會從用戶進程空間切換到內核空間運行一段時間再切換回來。默認狀況下recv會等到網絡數據到達而且複製到用戶進程空間或者發生錯誤時返回,而第4個參數flags可讓它立刻返回。less

  • 阻塞IO模型

使用recv的默認參數一直等數據直到拷貝到用戶空間,這段時間內進程始終阻塞。A同窗用杯子裝水,打開水龍頭裝滿水而後離開。這一過程就能夠當作是使用了阻塞IO模型,由於若是水龍頭沒有水,他也要等到有水並裝滿杯子才能離開去作別的事情。很顯然,這種IO模型是同步的。異步

image

  • 非阻塞IO模型

改變flags,讓recv無論有沒有獲取到數據都返回,若是沒有數據那麼一段時間後再調用recv看看,如此循環。B同窗也用杯子裝水,打開水龍頭後發現沒有水,它離開了,過一會他又拿着杯子來看看……在中間離開的這些時間裏,B同窗離開了裝水現場(回到用戶進程空間),能夠作他本身的事情。這就是非阻塞IO模型。可是它只有是檢查無數據的時候是非阻塞的,在數據到達的時候依然要等待複製數據到用戶空間(等着水將水杯裝滿),所以它仍是同步IO。函數

image

  • IO複用模型

這裏在調用recv前先調用select或者poll,這2個系統調用均可以在內核準備好數據(網絡數據到達內核)時告知用戶進程,這個時候再調用recv必定是有數據的。所以這一過程當中它是阻塞於select或poll,而沒有阻塞於recv,有人將非阻塞IO定義成在讀寫操做時沒有阻塞於系統調用的IO操做(不包括數據從內核複製到用戶空間時的阻塞,由於這相對於網絡IO來講確實很短暫),若是按這樣理解,這種IO模型也能稱之爲非阻塞IO模型,可是按POSIX來看,它也是同步IO,那麼也和樓上同樣稱之爲同步非阻塞IO吧。性能

這種IO模型比較特別,分個段。由於它能同時監聽多個文件描述符(fd)。這個時候C同窗來裝水,發現有一排水龍頭,舍管阿姨告訴他這些水龍頭都尚未水,等有水了告訴他。因而等啊等(select調用中),過了一會阿姨告訴他有水了,但不知道是哪一個水龍頭有水,本身看吧。因而C同窗一個個打開,往杯子裏裝水(recv)。這裏再順便說說鼎鼎大名的epoll(高性能的代名詞啊),epoll也屬於IO複用模型,主要區別在於舍管阿姨會告訴C同窗哪幾個水龍頭有水了,不須要一個個打開看(固然還有其它區別)。spa

image

  • 信號驅動IO模型

經過調用sigaction註冊信號函數,等內核數據準備好的時候系統中斷當前程序,執行信號函數(在這裏面調用recv)。D同窗讓舍管阿姨等有水的時候通知他(註冊信號函數),沒多久D同窗得知有水了,跑去裝水。是否是很像異步IO?很遺憾,它仍是同步IO(省不了裝水的時間啊)。操作系統

image

  • 異步IO模型

調用aio_read,讓內核等數據準備好,而且複製到用戶進程空間後執行事先指定好的函數。E同窗讓舍管阿姨將杯子裝滿水後通知他。整個過程E同窗均可以作別的事情(沒有recv),這纔是真正的異步IO。code

image

最後,總結比較下五種IO模型:blog

總結

IO分兩階段:

1.數據準備階段
2.內核空間複製回用戶進程緩衝區階段

通常來說:阻塞IO模型、非阻塞IO模型、IO複用模型(select/poll/epoll)、信號驅動IO模型都屬於同步IO,由於階段2是阻塞的(儘管時間很短)。只有異步IO模型是符合POSIX異步IO操做含義的,無論在階段1仍是階段2均可以幹別的事。

  • ps:以上圖片均截自UNIX網絡編程卷1。
相關文章
相關標籤/搜索