本文主要分析了Linux的iostat命令的源碼,iostat的主要功能見博客:性能測試進階指南——基礎篇之磁盤IOlinux
iostat源碼共563行,應該算是Linux系統命令代碼比較少的了。源代碼中主要涉及到以下幾個Linux的內核文件:ios
第一步,從/proc/cpuinfo中獲取系統的cpu核心數,經過計算該文件中processor出現的次數即可以獲得cpu的核心數;性能
第二步,經過判斷文件/proc/diskstats和/proc/partitions是否存在,從而判斷linux的內核是2.4版本仍是2.6版本:若是/proc/diskstats文件存在,則爲2.6版本;不然判斷/proc/partitions是否存在,若存在,則爲2.4版本;測試
第三部,分析iostat命令輸入的參數,每一個參數的功能能夠在上一篇博客中找到:性能測試進階指南——基礎篇之磁盤IOui
第四步,初始化,獲取磁盤名稱。之內核2.6爲例,讀取文件/proc/diskstatsgoogle
104 0 cciss/c0d0 49787 19805 1597284 159946 20172754 28596938 390157514 1583532 0 1352168 1737502
第一個參數104和第二個參數0分別表明了major和minor,major是8的倍數,minor是16的倍數,只要同時符合這兩個的條件,其對應的第三個參數cciss/c0d0即是所須要獲取的磁盤名稱;.net
第五步,進入主循環:code
(1) 獲取/proc/diskstats中每一個磁盤的數據,例如:blog
104 0 cciss/c0d0 49787 19805 1597284 159946 20172754 28596938 390157514 1583532 0 1352168 1737502
每一個參數對應的值爲ci
104——major 0——minor 49787——rd_ios 19805——rd_merges 1597284——rd_sectors 159946——rd_ticks 20172754——wr_ios 28596938——wr_merges 390157514——wr_sectors 1583532——wr_ticks 1352168——ticks 1737502——aveq
(2) 獲取/proc/stat中的數據,計算cpu的平均時間:分別獲取cpu的user時間,nice時間,system時間,idle時間,iowait時間。計算中將nice時間併入user時間,將irq時間和softirq時間併入system時間。此處只計算cpu的平均和狀態,不計算每隔核單獨的狀態。
(3)計算deltams時間,其中HZ是Linux的系統頻率。
deltams = 1000.0 * ((new_cpu.user + new_cpu.system + new_cpu.idle + new_cpu.iowait) - (old_cpu.user + old_cpu.system + old_cpu.idle + old_cpu.iowait)) / ncpu / HZ; `
(4)計算IO
blkio.rd_ios = new_blkio[p].rd_ios - old_blkio[p].rd_ios; blkio.rd_merges = new_blkio[p].rd_merges - old_blkio[p].rd_merges; blkio.rd_sectors = new_blkio[p].rd_sectors - old_blkio[p].rd_sectors; blkio.rd_ticks = new_blkio[p].rd_ticks - old_blkio[p].rd_ticks; blkio.wr_ios = new_blkio[p].wr_ios - old_blkio[p].wr_ios; blkio.wr_merges = new_blkio[p].wr_merges - old_blkio[p].wr_merges; blkio.wr_sectors = new_blkio[p].wr_sectors - old_blkio[p].wr_sectors; blkio.wr_ticks = new_blkio[p].wr_ticks - old_blkio[p].wr_ticks; blkio.ticks = new_blkio[p].ticks - old_blkio[p].ticks; blkio.aveq = new_blkio[p].aveq - old_blkio[p].aveq; n_ios = blkio.rd_ios + blkio.wr_ios; n_ticks = blkio.rd_ticks + blkio.wr_ticks; n_kbytes = (blkio.rd_sectors + blkio.wr_sectors) / 2.0; queue = blkio.aveq / deltams; size = n_ios ? n_kbytes / n_ios : 0.0; wait = n_ios ? n_ticks / n_ios : 0.0; svc_t = n_ios ? blkio.ticks / n_ios : 0.0; busy = 100.0 * blkio.ticks / deltams; if (busy > 100.0) busy = 100.0;
rd_sectors和wr_sectors是扇區數,若是須要換算成KB等單位,須要除以2,1KB=2*512Bytes。512Bytes爲1個扇區數。
(5)計算CPU
cpu.user = new_cpu.user - old_cpu.user; cpu.system = new_cpu.system - old_cpu.system; cpu.idle = new_cpu.idle - old_cpu.idle; cpu.iowait = new_cpu.iowait - old_cpu.iowait; total = (cpu.user + cpu.system + cpu.idle + cpu.iowait) / 100.0; printf("%3.0f %3.0f ", cpu.user / total, cpu.system / total); if (kernel == 6) printf("%3.0f ", cpu.iowait / total); printf("%3.0f", cpu.idle / total);
(6) Save old stats:
old_blkio[p] = new_blkio[p]; old_cpu = new_cpu;
每隔採樣時間循環執行第五步。
從源碼中能夠看出,第一次獲取的時候,是沒有old stats的,全部的old stats值均爲0,即iostat在第一次輸出的值爲Linux啓動以後至當前時間的一個平均狀態值,在以後的輸出值則爲系統當前的實時磁盤I/O信息和CPU信息。