內核很多重要子系統均通過proc文件的方式,將自身的一些統計信息輸出,方便最終用戶查看各子系統的運行狀態,這些統計信息被稱為metrics。 直接查看metrics並不能獲取到有用的信息,一般都是由特定的應用程式(htop/sar/iostat等)每隔一段時間讀取相關metrics,併進行相應計算, ...
內核很多重要子系統均通過proc文件的方式,將自身的一些統計信息輸出,方便最終用戶查看各子系統的運行狀態,這些統計信息被稱為metrics。 直接查看metrics並不能獲取到有用的信息,一般都是由特定的應用程式(htop/sar/iostat等)每隔一段時間讀取相關metrics,併進行相應計算,給出更具用戶可讀性的輸出。 常見的metrics文件有:
• cpu調度統計信息的/proc/stat
• cpu負載統計信息的/proc/loadavg
通用塊設備層也有一個重要的統計信息
• /proc/diskstats內核通過diskstats文件,將通用塊設備層的一些重要指標以文件的形式呈現給用戶
首先來看下diskstats裡面都有些什麼,下麵截取的是一個diskstats文件內容:
雖然如上面提到的,這些數字看上去完全沒有規律。不過若想研究內核通用塊設備層的統計實現方式,還是得一個一個欄位的分析。
# cat /proc/diskstats 2 0 fd0 0 0 0 0 0 0 0 0 0 0 0 11 0 sr0 18 0 2056 98 0 0 0 0 0 90 98 8 0 sda 5941 81 508270 54421 2051 3068 49868 15639 0 13973 69944 8 1 sda1 159 0 9916 304 11 2 68 28 0 292 332 8 2 sda2 5751 81 495010 54034 2040 3066 49800 15611 0 13834 69529 253 0 dm-0 5662 0 485850 54998 5106 0 49800 31524 0 13807 86522 253 1 dm-1 90 0 4920 156 0 0 0 0 0 123 156
/proc/diskstats有11(從F4開始)個欄位,以下內核文檔解釋了它們的含義https://www.kernel.org/doc/Documentation/iostats.txt,我重新表述了一下,註意除了欄位#9(F12)之外都是累計值,從系統啟動之後一直累加:
1. (rd_ios)讀操作的次數。
2. (rd_merges)合併讀操作的次數。如果兩個讀操作讀取相鄰的數據塊時,可以被合併成一個,以提高效率。合併的操作通常是I/O scheduler(也叫elevator)負責的。
3. (rd_sectors)讀取的扇區數量。
4. (rd_ticks)讀操作消耗的時間(以毫秒為單位)。每個讀操作從__make_request()開始計時,到end_that_request_last()為止,包括了在隊列中等待的時間。
5. (wr_ios)寫操作的次數。
6. (wr_merges)合併寫操作的次數。
7. (wr_sectors)寫入的扇區數量。
8. (wr_ticks)寫操作消耗的時間(以毫秒為單位)。
9. (in_flight)當前未完成的I/O數量。在I/O請求進入隊列時該值加1,在I/O結束時該值減1。
註意:是I/O請求進入隊列時,而不是提交給硬碟設備時。
10. (io_ticks)該設備用於處理I/O的自然時間(wall-clock time)。
請註意io_ticks與rd_ticks(欄位#4)和wr_ticks(欄位#8)的區別,rd_ticks和wr_ticks是把每一個I/O所消耗的時間累加在一起,因為硬碟設備通常可以並行處理多個I/O,所以rd_ticks和wr_ticks往往會比自然時間大。而io_ticks表示該設備有I/O(即非空閑)的時間,不考慮I/O有多少,只考慮有沒有。在實際計算時,欄位#9(in_flight)不為零的時候io_ticks保持計時,欄位#9(in_flight)為零的時候io_ticks停止計時。
11. (time_in_queue)對欄位#10(io_ticks)的加權值。欄位#10(io_ticks)是自然時間,不考慮當前有幾個I/O,而time_in_queue是用當前的I/O數量(即欄位#9 in-flight)乘以自然時間。雖然該欄位的名稱是time_in_queue,但並不真的只是在隊列中的時間,其中還包含了硬碟處理I/O的時間。iostat在計算avgqu-sz時會用到這個欄位。
以sda磁碟為例: 8 0 sda 5941 81 508270 54421 2051 3068 49868 15639 0 13973 69944
域 | Value | Quoted | 解釋 |
F1 | 8 | major number | 此塊設備的主設備號 |
F2 | 0 | minor mumber | 此塊設備的次設備號 |
F3 | sda | device name | 此塊設備名字 |
F4 | 5941 | reads completed successfully | 成功完成的讀請求次數 |
F5 | 81 | reads merged | 讀請求的次數 |
F6 | 508270 | sectors read | 讀請求的扇區數總和 |
F7 | 54421 | time spent reading (ms) | 讀請求花費的時間總和 |
F8 | 2051 | writes completed | 成功完成的寫請求次數 |
F9 | 3068 | writes merged | 寫請求合併的次數 |
F10 | 49868 | sectors written | 寫請求的扇區數總和 |
F11 | 15639 | time spent writing (ms) | 寫請求花費的時間總和 |
F12 | 0 | I/Os currently in progress | 次塊設備隊列中的IO請求數 |
F13 | 13973 | time spent doing I/Os (ms) | 塊設備隊列非空時間總和 |
F14 | 69944 | weighted time spent doing I/Os (ms) | 塊設備隊列非空時間加權總和 |
流程圖
下圖是Linux內核通用塊設備層IO請求處理的完整流程,如圖例所示,所有的統計相關處理均有用不同顏色標註。 在進行深入分析前,請大致瀏覽圖片,對整個流程有一個大致印象。
更詳細的內容,請閱讀:http://ykrocku.github.io/blog/2014/04/11/diskstats/