[學習如逆水行舟,不進則退]
對於linux中一些常用的寫操作,對比一下direct和sync的區別,後面會專門起個專題講一下linux中的快取機制和page cache
linux中sync和direct區別
o_direct
繞過緩衝區快取記憶體,直接io
直接io:linux允許應用程式在執行磁碟io時繞過緩衝區快取記憶體,從使用者空間直接將資料傳遞到檔案或磁碟裝置,稱為直接io(direct io)或者裸io(raw io)
應用場景:資料庫系統,其快取記憶體和io優化機制均自成一體,無需核心消耗cpu時間和記憶體去完成相同的任務
弊端:可能會大大降低效能,核心對緩衝區告訴快取做了不少優化,包括:按順序預讀取,在成簇磁碟塊上執行io,允許訪問同一檔案的多個程序共享快取記憶體的緩衝區
注意可能發生的不一致性:若一程序以o_direct標誌開啟某檔案,而另一程序以普通(即使用了快取記憶體緩衝區)開啟同一檔案,則由直接io所讀寫的資料與緩衝區快取記憶體中內容之間不存在一致性,應盡量避免這一場景
使用直接io需要遵守的一些限制:
1、用於傳遞資料的緩衝區,其記憶體邊界必須對齊為塊大小的整數倍
2、資料傳輸的開始點,即檔案和裝置的偏移量,必須是塊大小的整數倍
3、待傳遞資料的長度必須是塊大小的整數倍。
不遵守上述任一限制均將導致einval錯誤。
o_sync
以同步方式寫入檔案
功能:強制重新整理核心緩衝區到輸出檔案。這是有必要的,因為為了資料安全,需要確保將資料真正寫入磁碟或者磁碟的硬體告訴快取中
同步io的定義:某一io操作,要麼已成功完成到磁碟的資料傳遞,要麼被診斷為不成功。
linux定義了兩種同步io完成型別:
1、確保針對檔案的一次更新傳遞了足夠的資訊(部分檔案元資料)到磁碟,以便於之後對資料的獲取
2、確保針對檔案的一次更新傳遞了所有的資訊(所有檔案元資料)到磁碟,即使有些在後續對檔案資料的操作並不需要。
常用函式
fsync 作用:fsync()系統呼叫將使緩衝資料和fd相關的所有元資料都重新整理到磁碟上
fdatasync 作用:fdatasync()系統呼叫的作用類似fsync(),只是強制檔案處於synchronized io data integrity compeletion狀態。
sync系統呼叫 作用:sync()系統呼叫會使包含更新檔案資訊的所有核心緩衝區(即資料塊、指標塊、元資料等)重新整理到磁碟上。
detail:若內容發生變化的核心緩衝區在30s內未經顯式方式同步到磁碟上,則一條長期執行的核心執行緒會確保將其重新整理到磁碟上。這一做法是為了規避緩衝區與相關磁碟檔案內容長期處於不一致狀態
使所有寫入同步:o_sync 呼叫open後,每個write呼叫會自動將檔案資料和元資料重新整理到磁碟上,即按照synchronized io file integrity completion的要求執行寫操作
兩者區別:fdatasync()可能會減少磁碟操作的次數,由fsync()呼叫請求的兩次變成一次。例如,修改了檔案的資料,而檔案大小不變,那麼呼叫fdatasync呼叫請求只強制進行了資料更新,相比之下,fsync()呼叫會強制將元資料傳遞到磁碟上,而元資料和檔案資料通常駐留在磁碟的不同區域,更新這些資料需要反覆在整個磁碟上執行尋道操作
有無o_sync效能對比
場景:將一百萬位元組寫入乙個ext2檔案系統上的新建立檔案,比較寫入時間
結果結論
採用o_sync標誌(或者頻繁呼叫fsync(), fdatasync()或sync())對效能影響極大。
效能下降的直接表現為執行總用時大為增加:在緩衝區為1位元組的情況下,執行時間相差1000多倍。
以o_sync標誌執行寫操作時執行總用時和cpu時間之間的巨大差異(1030 - 98.8),原因是系統在每個緩衝區中將資料向磁碟傳遞時會把程式阻塞起來
io緩衝層次關係
首先,通過stdio庫將使用者資料傳遞到stdio緩衝區,該緩衝區位於使用者態記憶體區。
當緩衝區填滿,stdio庫會呼叫write()系統呼叫,將資料傳遞到核心高速緩衝區,該緩衝區位於核心態記憶體區。
最終,核心發起磁碟操作
左側虛線方框中為可於任何時刻顯式強制重新整理各類緩衝區的呼叫。
右側所示為促使重新整理自動化的呼叫:通過禁用stdio的緩衝,和在檔案輸出類的系統呼叫中啟用同步,從而使每個write()呼叫立刻重新整理到磁碟
區別o_direct:任何讀寫操作都只在使用者態位址空間和磁碟之間傳送而不經過page cache
o_sync: 只影響寫操作,block當前寫程序,先從使用者態記憶體寫入page cache, 再從page cache寫入磁碟,然後才返回到使用者程序
o_direct: 無緩衝的輸入、輸出
o_sync:以同步io方式開啟檔案
golang中併發sync和channel
golang中實現併發非常簡單,只需在需要併發的函式前面新增關鍵字 go 但是如何處理go併發機制中不同goroutine之間的同步與通訊,golang 中提供了sync包和channel機制來解決這一問題 sync 包提供了互斥鎖這類的基本的同步原語.除 once 和 waitgroup 之外的型...
golang中併發sync和channel
golang中實現併發非常簡單,只需在需要併發的函式前面新增關鍵字 go 但是如何處理go併發機制中不同goroutine之間的同步與通訊,golang 中提供了sync包和channel機制來解決這一問題 sync 包提供了互斥鎖這類的基本的同步原語.除 once 和 waitgroup 之外的型...
golang中併發sync和channel
golang中實現併發非常簡單,只需在需要併發的函式前面新增關鍵字 go 但是如何處理go併發機制中不同goroutine之間的同步與通訊,golang 中提供了sync包和channel機制來解決這一問題 sync 包提供了互斥鎖這類的基本的同步原語.除 once 和 waitgroup 之外的型...