bash iostat - ceragon/LinuxDoc GitHub Wiki

iostat

iostat 属于 sysstat 工程

完整日志

$ iostat
Linux 5.15.0-30-generic (ceragon-ThinkPad-T440p)        2022年05月17日  _x86_64_        (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           7.08    0.02    0.54    0.04    0.00   92.32

Device             tps    kB_read/s    kB_wrtn/s    kB_dscd/s    kB_read    kB_wrtn    kB_dscd
loop0             0.00         0.00         0.00         0.00         17          0          0
loop1             0.00         0.01         0.00         0.00        351          0          0
loop10            0.00         0.01         0.00         0.00        188          0          0
loop11            0.00         0.01         0.00         0.00        347          0          0
loop12            0.00         0.00         0.00         0.00         14          0          0
loop2             0.04         0.74         0.00         0.00      22103          0          0
loop3             0.00         0.04         0.00         0.00       1101          0          0
loop4             0.11         1.70         0.00         0.00      51019          0          0
loop5             0.10         5.94         0.00         0.00     178375          0          0
loop6             0.10         0.27         0.00         0.00       8216          0          0
loop7             0.00         0.01         0.00         0.00        350          0          0
loop8             0.04         0.47         0.00         0.00      14133          0          0
loop9             0.00         0.05         0.00         0.00       1652          0          0
sda               0.03         0.19         2.58         0.00       5624      77396          0
sdb              13.25       250.90       343.41         0.00    7537140   10316277          0
sr0               0.00         0.00         0.00         0.00          2          0          0

标题

只考虑IO数据的部分,下面用于显示标题行

void write_disk_stat_header(int *fctr, int *tab, int hpart) {
    char *units, *spc;
    units = "kB";
	spc = " ";
    if (!DISPLAY_PRETTY(flags)) {
		printf("Device       ");
	}
    if (DISPLAY_EXTENDED(flags)) {
    } else {
        if (DISPLAY_SHORT_OUTPUT(flags)) {
        } else {
            printf("      tps   %s%s_read/s   %s%s_wrtn/s   %s%s_dscd/s   %s%s_read   %s%s_wrtn   %s%s_dscd",
			       spc, units, spc, units, spc, units, spc, units, spc, units, spc, units);
        }
    }
}

数据显示

int flags = 0;
struct io_device *dev_list = NULL;
void write_stats(int curr, struct tm *rectime, int skip) {
    int h, hl = 0, hh = 0, fctr = 1, tab = 4, next = FALSE;
    unsigned long long itv;
    /* Calculate time interval in 1/100th of a second */
	itv = get_interval(uptime_cs[!curr], uptime_cs[curr]);
    if (DISPLAY_DISK(flags)) {
        struct io_stats *ioi, *ioj, iozero;
        for (h = hl; h <= hh; h++) {
            for (d = dev_list; ; d = dnext) {
                dnext = d->next;
                ioi = d->dev_stats[curr];
				ioj = d->dev_stats[!curr];
                dev_name = get_device_name(d->major, d->minor, NULL, 0,
							   DISPLAY_DEVMAP_NAME(flags),
							   DISPLAY_PERSIST_NAME_I(flags),
							   FALSE, d->name);
                if (!skip) {
                    if (DISPLAY_EXTENDED(flags)) {
                    } else {
                        // itv 是时间差值
                        // fctr 默认值是1
                        write_basic_stat(itv, fctr, d, ioi, ioj, tab, dev_name);
                    }
                }
            }
        }
    }
}
void write_basic_stat(unsigned long long itv, int fctr,
		      struct io_device *d, struct io_stats *ioi,
		      struct io_stats *ioj, int tab, char *dname) {
    unsigned long long rd_sec, wr_sec, dc_sec; 
    rd_sec = ioi->rd_sectors - ioj->rd_sectors;
    wr_sec = ioi->wr_sectors - ioj->wr_sectors;
    dc_sec = ioi->dc_sectors - ioj->dc_sectors;
    if (DISPLAY_JSON_OUTPUT(flags)) {
    } else {
		write_plain_basic_stat(itv, fctr, ioi, ioj, dname,
				       rd_sec, wr_sec, dc_sec);
	}
}
void write_plain_basic_stat(unsigned long long itv, int fctr,
			    struct io_stats *ioi, struct io_stats *ioj,
			    char *devname, unsigned long long rd_sec,
			    unsigned long long wr_sec, unsigned long long dc_sec) {
    double rsectors, wsectors, dsectors;
    // ((ioi - ioj) / itv) * 100
    rsectors = S_VALUE(ioj->rd_sectors, ioi->rd_sectors, itv);
	wsectors = S_VALUE(ioj->wr_sectors, ioi->wr_sectors, itv);
	dsectors = S_VALUE(ioj->dc_sectors, ioi->dc_sectors, itv);
    if (!DISPLAY_UNIT(flags)) {
		rsectors /= fctr;
		wsectors /= fctr;
		dsectors /= fctr;
	}
    if (!DISPLAY_PRETTY(flags)) {
		cprintf_in(IS_STR, "%-13s", devname, 0);
	}
    /* tps */
	cprintf_f(NO_UNIT, 1, 8, 2,
		  /* Origin (unmerged) flush operations are counted as writes */
		  S_VALUE(ioj->rd_ios + ioj->wr_ios + ioj->dc_ios,
			  ioi->rd_ios + ioi->wr_ios + ioi->dc_ios, itv));
    if (DISPLAY_SHORT_OUTPUT(flags)) {
    } else {
        /* kB_read/s kB_wrtn/s kB_dscd/s */
		cprintf_f(DISPLAY_UNIT(flags) ? UNIT_SECTOR : NO_UNIT, 3, 12, 2,
			  rsectors, wsectors, dsectors);
        /* kB_read kB_wrtn kB_dscd */
		cprintf_u64(DISPLAY_UNIT(flags) ? UNIT_SECTOR : NO_UNIT, 3, 10,
			    DISPLAY_UNIT(flags) ? (unsigned long long) rd_sec
						: (unsigned long long) rd_sec / fctr,
			    DISPLAY_UNIT(flags) ? (unsigned long long) wr_sec
						: (unsigned long long) wr_sec / fctr,
			    DISPLAY_UNIT(flags) ? (unsigned long long) dc_sec
						: (unsigned long long) dc_sec / fctr);
    }
    printf("\n");
}

dev_list 赋值

数据样例

$ cat /proc/diskstats 
   7       0 loop0 14 0 34 1 0 0 0 0 0 20 1 0 0 0 0 0 0
   7       1 loop1 45 0 702 46 0 0 0 0 0 72 46 0 0 0 0 0 0
   7       2 loop2 1123 0 48088 263 0 0 0 0 0 2676 263 0 0 0 0 0 0
   7       3 loop3 61 0 2208 45 0 0 0 0 0 64 45 0 0 0 0 0 0
   7       4 loop4 3465 0 106416 634 0 0 0 0 0 6288 634 0 0 0 0 0 0
   7       5 loop5 2926 0 356756 907 0 0 0 0 0 4128 907 0 0 0 0 0 0
   7       6 loop6 3153 0 16442 137 0 0 0 0 0 1120 137 0 0 0 0 0 0
   7       7 loop7 43 0 700 14 0 0 0 0 0 28 14 0 0 0 0 0 0
   8       0 sda 795 24 11305 143450 108 15 154792 4470 0 13432 148450 0 0 0 0 30 529
   8       1 sda1 370 24 8714 133638 108 15 154792 4470 0 4092 138108 0 0 0 0 0 0
   8      16 sdb 321538 85929 15917616 133118 96261 489238 21298746 418453 0 568976 579014 0 0 0 0 13306 27442
   8      17 sdb1 26 0 208 364 0 0 0 0 0 384 364 0 0 0 0 0 0
   8      18 sdb2 147 23 10992 486 2 0 2 0 0 544 486 0 0 0 0 0 0
   8      19 sdb3 320822 85906 15900258 131753 96259 489238 21298744 418453 0 568312 550207 0 0 0 0 0 0
  11       0 sr0 10 0 4 7 0 0 0 0 0 28 7 0 0 0 0 0 0
   7       8 loop8 1102 0 28980 216 0 0 0 0 0 1984 216 0 0 0 0 0 0
   7      11 loop11 43 0 694 11 0 0 0 0 0 44 11 0 0 0 0 0 0
   7       9 loop9 145 0 8316 49 0 0 0 0 0 376 49 0 0 0 0 0 0
   7      10 loop10 29 0 378 7 0 0 0 0 0 60 7 0 0 0 0 0 0
   7      12 loop12 73 0 2216 3 0 0 0 0 0 48 3 0 0 0 0 0 0

读取信息

void read_diskstats_stat_work(int curr, char *diskstats) {
    // diskstats = /proc/diskstats
    FILE *fp;
    char line[256];
    struct io_stats sdev;
    int i;
    unsigned int ios_pgr, tot_ticks, rq_ticks, wr_ticks, dc_ticks, fl_ticks;
	unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios;
	unsigned long wr_merges, rd_sec_or_wr_ios, wr_sec;
	unsigned long dc_ios, dc_merges, dc_sec, fl_ios;
	unsigned int major, minor;
    if ((fp = fopen(diskstats, "r")) == NULL)
		return;
    while (fgets(line, sizeof(line), fp) != NULL) {
        i = sscanf(line, "%u %u %s %lu %lu %lu %lu %lu %lu %lu %u %u %u %u %lu %lu %lu %u %lu %u",
			   &major, &minor, dev_name,
			   &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios, &rd_ticks_or_wr_sec,
			   &wr_ios, &wr_merges, &wr_sec, &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks,
			   &dc_ios, &dc_merges, &dc_sec, &dc_ticks,
			   &fl_ios, &fl_ticks);
        if (i >= 14) {
            // 第 4个参数
            sdev.rd_ios     = rd_ios;
            // 第 8个参数
            sdev.wr_ios     = wr_ios;
            // 第 15个参数
            sdev.dc_ios     = dc_ios;
            // 第 6个参数
            sdev.rd_sectors = rd_sec_or_wr_ios;
            // 第 10个参数
            sdev.wr_sectors = wr_sec;
            // 第 17个参数
            sdev.dc_sectors = dc_sec;
        }
        d = add_list_device(&dev_list, dev_name, 0, major, minor);
		if (d != NULL) {
			*d->dev_stats[curr] = sdev;
		}
    }
}

参数解释

  • tps : 单位时间 IO 的请求数
  • read/s: 单位时间内平均每秒 读 IO 的数量
  • wrtn/s: 单位时间平均每秒 写 IO 的数量
  • read: 单位时间内 读 IO的数据量,单位KB
  • wrtn: 单位时间内 读 IO的数据量, 单位KB
⚠️ **GitHub.com Fallback** ⚠️