同步IO,異步IO,延遲IO,這三個概念用了蠻久了,可是一直以爲理解的不太系統。看了很多文章,大都說的先後矛盾。最近花了一些時間,進行了一個總結,寫下心得。linux
同步IO:當前一個IO真正完成後,後一個IO才能夠發出。如posix的read, write等系統調用。緩存
異步IO:每一個IO請求,是否完成,都不會影響後續IO的發出。如glibc的aio,以及linux的libaio,等等。異步
Buffered IO:
讀取:硬盤->內核緩衝區->用戶緩衝區;
寫回:數據會從用戶地址空間拷貝到操做系統內核地址空間的頁緩存中去,這是write就會直接返回,操做系統會在恰當的時機寫入磁盤,這就是傳說中的Buffered IO。buffer io 對寫IO而言有write back和write through。write back先寫入到內存中,一段時間後,由內核線程寫入到磁盤。因爲內存比磁盤快不少,因此write back的速度很快。write back有一個缺點,就是當你掉電時,可能會丟失數據。這時候write through 就粉墨登場了,write through和write back相比,在寫入內存的同時也寫入到磁盤中,那爲何要寫入到內存中呢,不是畫蛇添足嗎,這可能爲了之後讀的更快。不過我沒有看到有文件系統實現 write through的,對文件系統來講,buffer io的寫就是write back模式。ceph filestore的寫數據部分,也是write back模式。操作系統
非Buffered IO(Direct IO):
對於自緩存應用程序來講,緩存 I/O 明顯不是一個好的選擇。所以出現了DIRECT IO。然而想象一下,不經內核緩衝區,直接寫磁盤,必然會引發阻塞。因此一般DIRECT IO與AIO會一塊兒出現。.net
延遲IO:
其實,提及延遲IO,就是延遲寫(不存在延遲讀一說)。延遲寫的意思是指:寫操做的時候,不只要寫到kernel的page cache中,還要同時下刷到disk中。延遲寫的控制,在open一個文件的時候指定:
int open(const char *pathname, int flags, ... /* mode_t mode*/);
1) O_SYNC: write操做,將會被阻住,直到數據和元數據被寫到了物理硬盤上。線程
2) O_DSYNC: write操做,將會被阻住,直到數據被寫到了物理硬盤上。翻譯
這裏,SYNC是synchronous IO的縮寫。字面意思,甚至不少資料,都翻譯成同步IO。我認爲,這裏的「同步」,跟我上文提到的同步/異步IO,不是一個概念。若是硬要翻譯成同步,那麼也是指kernel cache和底層硬件disk之間的同步。因此,這裏SYNC,我認爲理解成「非延遲」,更加準確一些。blog
有篇文章,叫作《O_DIRECT和O_SYNC詳解》,裏面有個圖,很清楚:內存
上圖中,左側虛線方框中爲可於任什麼時候刻顯式強制刷新各種緩衝區的調用。get
右側所示爲促使刷新自動化的調用:經過禁用stdio的緩衝,和在文件輸出類的系統調用中啓用同步,從而使每一個write()調用馬上刷新到磁盤。