IO—— Input Output簡寫 也就是常說的輸入輸出
我覺得這東西其實是相對而言的,比如我現在要用的是QQ文件上傳,那相對於QQ這個應用而言,Input就是本地磁盤的文件到QQ應用,output就是本地QQ應用到QQ的服務器上
再比如我現在用java開發一個web后端,前端想從我這下載圖片,相對於web后端而言,input就是文件服務器到后端服務器,output就是后端服務器到web前端
所以其實對IO來講 講的就是傳輸,可以簡單的理解為輸入輸出流,用來傳輸字節。 根據不同的場景也分為不同的IO類型 作為開發人員最關心的莫過於網絡IO/磁盤IO
我們從一個例子入手,
從本地磁盤讀取一個字節 是怎樣實現的?
我們在應用程序層發出指令 要讀一個字節 調用c函數庫,內核就需要 IO 引擎、VFS、PageCache、通用塊管理層、IO 調度層等許多個組件來進行復雜配合才能完成。
最后傳到硬件層也就是磁盤,磁盤進行轉磁頭啊尋址啊 找到數據。
完整的流程是這樣的,但是linux內核面向用戶黑盒的做了很多優化,用緩存的機制 多層緩存幫助我們盡量避免磁盤尋址 (磁盤尋址可不是最費力氣的嗎)
第一層緩存 PageCache
Page Cache。頁高速緩存。是一個純內存的工作組件。
Page Cache 是以頁為單位的,Linux 頁大小一般是 4KB (??這不就是mysql InnoDB索引的底層最小存儲單位頁嗎 冥冥之中好像懂了什么..)
Linux 內核使用搜索樹來高效管理大量的頁面。
通過PageCache,Linux 就可以把一些磁盤上的文件數據保留在內存中,然后來給訪問相對比較慢的磁盤來進行訪問加速。
按照上圖從上到下走,如果PageCache中命中,則不需要繼續往下走
第二層優化 IO調度層
IO 請求到達這里時,並不一定會立即被執行。因為調度層會從全局出發,盡量讓整體磁盤 IO 性能最大化。
對於機械硬盤來說,調度層會盡量讓磁頭類似電梯那樣工作,先往一個方向走,到頭再回來,這樣整體效率會比較高一些。(也就是常說的電梯算法)
第三層緩存 磁盤緩存
這不屬於linux層,由磁盤自帶,,因為現在的磁盤本身就會帶一塊緩存。另外現在的服務器都會組建磁盤陣列,在磁盤陣列里的核心硬件Raid卡里也會集成RAM作為緩存。
讀一個字節時IO會有多大?
整個 IO 過程中涉及到了好幾個內核組件。而每個組件之間都是采用不同長度的塊來管理磁盤數據的。
整個內核工作流中,最小的工作單位是磁盤的扇區,為512字節。 所以一次磁盤IO讀取最小最小是讀取一個扇區,也就是512字節
另外 block、page cache 等高層組件工作單位更大。其中 Page Cache 的大小是一個內存頁 4KB。所以一般一次磁盤讀取是多個扇區(512字節)一起進行的。
假設通用塊層 IO 的段就是一個內存頁的話,一次磁盤 IO 就是 4 KB(8 個 512 字節的扇區)一起進行讀取。
最后,還有預讀取策略(提前讀前后數據到緩存中,方便連續讀取) 所以一次磁盤IO讀取理應是大於4K