熟悉mysql和kafka的刷臟頁流程后,都知道內存中的臟頁不會立刻刷到磁盤,下面就細化下流程
寫操作:
用戶調用 fwrite 把數據寫入 C 庫標准 IObuffer 后就返回,即寫操作通常是異
步操作;
數據寫入 C 庫標准 IObuffer 后,不會立即刷新到磁盤,會將多次小數據量相
鄰寫操作先緩存起來合井,最終調用 write 函數一次性寫入(或者將大塊數據分解多次
write 調用)頁緩存;
數據到達頁緩存后也不會立 即刷新到磁盤,內核有 pdflush 線程
在不停地檢測臟頁,判斷是否要寫回到磁盤,如果是則發起磁盤 I/O 請求。
總結:用戶進程內存頁--->C庫IObuffer--->操作系統的頁緩存--->落盤
注意:C標准庫的I/O緩沖區也在用戶空間
讀操作:
用戶調用 fread 到 C 庫標准 IObuffer 中讀取數據,如果成功則返回,否則繼
續;
到頁緩存中讀取數據,如果成功則返回,否則繼續;
發起 I/O請求,讀取數據后緩存 buffer 和 C 庫標准 IObuffer 並返回。
可以看出,讀操作是同步請求。
I/O請求處理: 通用塊層根據 I/O請求構造一個或多個 bio 結構並提交給調度層;
調度器將 bio 結構進行排序和合並組織成隊列且確保讀寫操作盡可能理想:
將一個或多個進程的讀操作合並到一起讀,將一個或多個進程的寫操作合並到一起寫,盡可能變隨機為順序 (因為隨機讀寫比順序讀寫要慢),讀必須優先滿足, 而寫也不能等太久 。
bio結構就是kernel中block I/O的基礎容器,它是在”linux/bio.h”中被定義的。這個結構將當前激活的block I/O操作表示為一個segment的list。segment就是內存中一塊連續的buffer