背景html
在不少IO場景中,咱們常常須要確保數據已經安全的寫到磁盤上,以便在系統宕機重啓以後還能讀到這些數據。可是咱們都知道,linux系統的IO路徑仍是很複雜的,分爲不少層,每一層均可能會有buffer來加速IO讀寫。同時,用戶態的應用程序和庫函數也可能擁有本身的buffer,這又給IO路徑增長了一些複雜性。可見,要想保證數據安全的寫到磁盤上,並非簡單調一個write/fwrite就能夠搞定的。
那麼要怎麼作呢?不少人會想到不少辦法,好比:fflush()、fsync()、fdatasync()、sync()、open()使用O_DIRECT或O_SYNC標誌等。嗯,這些手段(或者某些組合)的確能夠保證數據安全的持久化,那麼它們之間有什麼區別呢?fflush()和fsync()有啥區別?O_DIRECT是啥意思,它能夠保證數據安全的持久化嗎?O_DIRECT和O_SYNC區別什麼?O_SYNC和fsync()呢?fsync能完成msync的功能嗎?本文將試圖理解、解釋這些概念的做用和區別。linux
Linux IO安全
所謂一圖勝千言,爲了解析清楚這些概念的區別,我特地畫了一張圖,仔細看,應該能夠清晰的看出它們的做用和區別。
這裏重點說一下O_DIRECT和O_SYNC,首先要明確的是,O_DIRECT只是說數據不會通過page cache(通常用在用戶態本身管理buffer)而是直接提交給塊設備層,可是不會同步等待數據安全寫入磁盤以後才返回(好比數據可能還在塊層排隊或者在磁盤本身的cache中)。而O_SYNC標誌,雖然數據仍是會寫page cache,可是此時會採用write through的策略,並同步等待數據安全寫入磁盤後纔會返回。所以若是同時使用O_DIRECT和O_SYNC,則表示數據不會通過page cache並同步等待數據安全寫入磁盤才返回,固然這樣IO的性能會很是低下。
因爲O_DIRECT會bypass page cache,所以若是有另外一個進程使用普通的方式讀文件,有可能會出現數據不一致的現象,這個也須要注意。
爲了作一下輔助說明,此處我貼一下我探討過程當中看過的一些資料。首先是引用open系統調用:
http://man7.org/linux/man-pages/man2/open.2.html
相關參數的說明:
以及innodb相關的文檔:
https://lwn.net/Articles/457667/
fsync和fdatasync的區別:
http://man7.org/linux/man-pages/man2/fsync.2.html
msync:
http://man7.org/linux/man-pages/man2/msync.2.html
async
DAX函數
其實還有一種IO模式,就是DAX(Direct Access ),是否是看上去和O_DIRECT很像。這種模式須要filesystem和block driver都支持才能夠,通常主要用在non volatile memory上,本質上也是繞過page cache直接操做設備。DAX本文先不作深刻探討,後面我會本身寫一個支持DAX模式的ramdisk塊設備驅動,而後格式化爲ext4文件系統並-o dax模式掛載,再來詳細研究DAX的IO路徑。
最後附上Linux在常見場景下的io路徑跟蹤:
https://my.oschina.net/fileoptions/blog/3061822性能