1.阻塞io,linux下默認所有的io都是阻塞的,
當發起io操作時,程序阻塞,直到io完成才會返回。浪費cpu的資源。
2非阻塞io
當發起io操作后,程序會立即返回,之后程序不斷輪詢,判斷io是否就緒。這種情況下的輪訓就是傻輪詢,無論io是否就緒,會一直去問。但是好的一點是,在while的輪詢過程中可以做一些其它的事情。但是這種非阻塞io往往需要配合多線程達到高效率。因為服務器往往有多個客戶端的連接,單一線程要實現對多個連接的管理,往往需要通過隊列,對多個socket進行管理,這對用戶來說往往很困難(有幾個人能手寫linux內核對select或epoll的底層實現?),而多線程的切換又是十分消耗系統資源的,所以非阻塞io+多線程實現高性能服務器,往往效果也不是很好。
3.io多路復用(select/epoll)(reactor)
多線程是十分耗費系統資源的,那么我們自然而然就想到能否用單線程實現對多個客戶端socket的管理,在上面提到如果在用戶態完成這個任務是比較困難的,但是慶幸的是linux內核幫我們實現了這個復雜的操作,典型的兩種是select和epoll.二者的區別
select
用一個eventloop隊列去管理多個socket,沒有io時,select阻塞掛起,但是它只知道有數據到達,并不知道是那個fd(socket)的,所以需要遍歷所有的fd,找出真正被觸發的socket,執行其對應的處理函數。
epoll
epoll同樣維護了一個輪詢的eventloop,但是不同的是它在客戶端有數據到達時,會被顯示的告知是哪幾個socket被觸發,因此不需要再用o(n)的時間復雜度去輪詢,所以性能很高。epoll是單線程異步io,但是這種異步并不是那么純,因為數據。
4.信號驅動
不常用
5.異步io(被動告知異步)
沒有阻塞,就是當數據到達時,利用中斷機制切換到用戶態處理。io多路復用需要主動輪詢,用戶自己將數據從內核態地址空間拷貝到用戶態,而異步io會將數據的同步自動完成,用戶進程只需要去讀取數據即可。
異步io和io多路復用區別是異步io是事情做完了你通知我一聲,而io多路復用是事情可以做的話你告訴我一聲,我去做。
io多路復用會阻塞用戶socket,而異步io不會阻塞用戶線程。
io多路復用是同步io,因為用戶態還要去輪詢看看哪些事件可以就緒執行,(雖然操作系統已經觸發了對應事件,但是用戶還得去輪詢隊列中一遍遍查看)
異步io(異步非阻塞)用戶進程不會被阻塞。
阻塞:調用立即返回
非阻塞:調用不返回
同步: 我自己去問消息是否完成。
異步:主動告知我消息是否完成。