📄 iostat.c
字号:
* I/O in progress times the number of milliseconds spent doing I/O. * But the number of I/O in progress (field ios_pgr) happens to be * sometimes negative... */ nr_ios = (ioi->rd_ios - ioj->rd_ios) + (ioi->wr_ios - ioj->wr_ios); tput = ((double) nr_ios) * HZ / itv; util = S_VALUE(ioj->tot_ticks, ioi->tot_ticks, itv); svctm = tput ? util / tput : 0.0; /* * kernel gives ticks already in milliseconds for all platforms * => no need for further scaling. */ await = nr_ios ? ((ioi->rd_ticks - ioj->rd_ticks) + (ioi->wr_ticks - ioj->wr_ticks)) / nr_ios : 0.0; rd_sec = ioi->rd_sectors - ioj->rd_sectors; if ((ioi->rd_sectors < ioj->rd_sectors) && (ioj->rd_sectors <= 0xffffffff)) rd_sec &= 0xffffffff; wr_sec = ioi->wr_sectors - ioj->wr_sectors; if ((ioi->wr_sectors < ioj->wr_sectors) && (ioj->wr_sectors <= 0xffffffff)) wr_sec &= 0xffffffff; arqsz = nr_ios ? (rd_sec + wr_sec) / nr_ios : 0.0; printf("%-10s", shi->name); if (strlen(shi->name) > 10) printf("\n "); /* rrq/s wrq/s r/s w/s rsec wsec rqsz qusz await svctm %util */ printf(" %6.2f %6.2f %5.2f %5.2f %8.2f %8.2f %8.2f %8.2f %7.2f %6.2f %6.2f\n", S_VALUE(ioj->rd_merges, ioi->rd_merges, itv), S_VALUE(ioj->wr_merges, ioi->wr_merges, itv), S_VALUE(ioj->rd_ios, ioi->rd_ios, itv), S_VALUE(ioj->wr_ios, ioi->wr_ios, itv), ll_s_value(ioj->rd_sectors, ioi->rd_sectors, itv) / fctr, ll_s_value(ioj->wr_sectors, ioi->wr_sectors, itv) / fctr, arqsz, S_VALUE(ioj->rq_ticks, ioi->rq_ticks, itv) / 1000.0, await, /* The ticks output is biased to output 1000 ticks per second */ svctm, /* Again: ticks in milliseconds */ util / 10.0);}/* *************************************************************************** * Write basic stats, read from /proc/stat, /proc/{diskstats,partitions} * or from sysfs *************************************************************************** */void write_basic_stat(int curr, unsigned long long itv, int flags, int fctr, struct io_hdr_stats *shi, struct io_stats *ioi, struct io_stats *ioj){ unsigned long long rd_sec, wr_sec; printf("%-13s", shi->name); if (strlen(shi->name) > 13) printf("\n "); if (HAS_SYSFS(flags) || HAS_DISKSTATS(flags) || HAS_PPARTITIONS(flags)) { /* Print stats coming from /sys or /proc/{diskstats,partitions} */ rd_sec = ioi->rd_sectors - ioj->rd_sectors; if ((ioi->rd_sectors < ioj->rd_sectors) && (ioj->rd_sectors <= 0xffffffff)) rd_sec &= 0xffffffff; wr_sec = ioi->wr_sectors - ioj->wr_sectors; if ((ioi->wr_sectors < ioj->wr_sectors) && (ioj->wr_sectors <= 0xffffffff)) wr_sec &= 0xffffffff; printf(" %8.2f %12.2f %12.2f %10llu %10llu\n", S_VALUE(ioj->rd_ios + ioj->wr_ios, ioi->rd_ios + ioi->wr_ios, itv), ll_s_value(ioj->rd_sectors, ioi->rd_sectors, itv) / fctr, ll_s_value(ioj->wr_sectors, ioi->wr_sectors, itv) / fctr, (unsigned long long) rd_sec / fctr, (unsigned long long) wr_sec / fctr); } else { /* Print stats coming from /proc/stat */ printf(" %8.2f %12.2f %12.2f %10lu %10lu\n", S_VALUE(ioj->dk_drive, ioi->dk_drive, itv), S_VALUE(ioj->dk_drive_rblk, ioi->dk_drive_rblk, itv) / fctr, S_VALUE(ioj->dk_drive_wblk, ioi->dk_drive_wblk, itv) / fctr, (ioi->dk_drive_rblk - ioj->dk_drive_rblk) / fctr, (ioi->dk_drive_wblk - ioj->dk_drive_wblk) / fctr); }}/* *************************************************************************** * Print everything now (stats and uptime) *************************************************************************** */int write_stat(int curr, int flags, struct tm *loc_time){ int dev, i, fctr = 1; unsigned long long itv; struct io_hdr_stats *shi = st_hdr_iodev; struct io_stats *ioi, *ioj; struct io_dlist *st_dev_list_i; /* * Under very special circumstances, STDOUT may become unavailable, * This is what we try to guess here */ if (write(STDOUT_FILENO, "", 0) == -1) { perror("stdout"); exit(6); } /* Print time stamp */ if (DISPLAY_TIMESTAMP(flags)) { strftime(timestamp, sizeof(timestamp), "%X", loc_time); printf(_("Time: %s\n"), timestamp); } /* * itv is multiplied by the number of processors. * This is OK to compute CPU usage since the number of jiffies spent in the * different modes (user, nice, etc.) is the sum of all the processors. * But itv should be reduced to one processor before displaying disk * utilization. */ if (!comm_stats[!curr].uptime) /* * This is the first report displaying stats since system startup. * Only in this case we admit that the interval may be greater * than 0xffffffff, else it was an overflow. */ itv = comm_stats[curr].uptime; else /* uptime in jiffies */ itv = (comm_stats[curr].uptime - comm_stats[!curr].uptime) & 0xffffffff; if (!itv) itv = 1; if (!DISPLAY_DISK_ONLY(flags)) /* Display CPU utilization */ write_cpu_stat(curr, itv); if (cpu_nr) { /* On SMP machines, reduce itv to one processor (see note above) */ if (!comm_stats[!curr].uptime0) itv = comm_stats[curr].uptime0; else itv = (comm_stats[curr].uptime0 - comm_stats[!curr].uptime0) & 0xffffffff; if (!itv) itv = 1; } if (!DISPLAY_CPU_ONLY(flags)) { /* Display stats header */ write_stat_header(flags, &fctr); if (DISPLAY_EXTENDED(flags) && (HAS_OLD_KERNEL(flags) || HAS_PLAIN_KERNEL24(flags))) { /* No extended stats with old 2.2-2.4 kernels */ printf("\n"); return 1; } for (i = 0; i < iodev_nr; i++, shi++) { if (shi->used) { if (dlist_idx && !HAS_SYSFS(flags)) { /* * With sysfs, only stats for the requested devices are read. * With /proc/{diskstats,partitions}, stats for every devices * are read. Thus we need to check if stats for current device * are to be displayed. */ for (dev = 0; dev < dlist_idx; dev++) { st_dev_list_i = st_dev_list + dev; if (!strcmp(shi->name, st_dev_list_i->dev_name)) break; } if (dev == dlist_idx) /* Device not found in list: don't display it */ continue; } ioi = st_iodev[curr] + i; ioj = st_iodev[!curr] + i; if (!DISPLAY_UNFILTERED(flags)) { if (HAS_OLD_KERNEL(flags) || HAS_PLAIN_KERNEL24(flags)) { if (!ioi->dk_drive) continue; } else { if (!ioi->rd_ios && !ioi->wr_ios) continue; } } if (DISPLAY_EXTENDED(flags)) write_ext_stat(curr, itv, flags, fctr, shi, ioi, ioj); else write_basic_stat(curr, itv, flags, fctr, shi, ioi, ioj); } } printf("\n"); } return 1;}/* *************************************************************************** * Main loop: read I/O stats from the relevant sources, * and display them. *************************************************************************** */void rw_io_stat_loop(int flags, long int count, struct tm *loc_time){ int curr = 1; int next; do { /* Read kernel statistics (CPU, and possibly disks for old kernels) */ read_proc_stat(curr, flags); if (dlist_idx) { /* * A device or partition name was entered on the command line, * with or without -p option (but not -p ALL). */ if (HAS_DISKSTATS(flags) && !DISPLAY_PARTITIONS(flags)) read_diskstats_stat(curr, flags); else if (HAS_SYSFS(flags)) read_sysfs_dlist_stat(curr, flags); else if (HAS_PPARTITIONS(flags) && !DISPLAY_PARTITIONS(flags)) read_ppartitions_stat(curr, flags); } else { /* * No devices nor partitions entered on the command line * (for example if -p ALL was used). */ if (HAS_DISKSTATS(flags)) read_diskstats_stat(curr, flags); else if (HAS_SYSFS(flags)) read_sysfs_stat(curr,flags); else if (HAS_PPARTITIONS(flags)) read_ppartitions_stat(curr, flags); } /* Save time */ get_localtime(loc_time); /* Print results */ if ((next = write_stat(curr, flags, loc_time)) && (count > 0)) count--; fflush(stdout); if (count) { pause(); if (next) curr ^= 1; } } while (count);}/* *************************************************************************** * Main entry to the iostat program *************************************************************************** */int main(int argc, char **argv){ int it = 0, flags = 0; int opt = 1; int i; long count = 1; struct utsname header; struct io_dlist *st_dev_list_i; struct tm loc_time;#ifdef USE_NLS /* Init National Language Support */ init_nls();#endif /* Allocate structures for device list */ if (argc > 1) salloc_dev_list(argc - 1); /* Process args... */ while (opt < argc) { if (!strcmp(argv[opt], "-p")) { flags |= I_D_PARTITIONS; if (argv[++opt] && (strspn(argv[opt], DIGITS) != strlen(argv[opt])) && (strncmp(argv[opt], "-", 1))) { flags |= I_D_UNFILTERED; if (!strcmp(argv[opt], K_ALL)) { flags |= I_D_PART_ALL; opt++; } else { /* Store device name */ i = update_dev_list(&dlist_idx, device_name(argv[opt++])); st_dev_list_i = st_dev_list + i; st_dev_list_i->disp_part = TRUE; } } else flags |= I_D_PART_ALL; } else if (!strncmp(argv[opt], "-", 1)) { for (i = 1; *(argv[opt] + i); i++) { switch (*(argv[opt] + i)) { case 'c': flags |= I_D_CPU_ONLY; /* Display cpu usage only */ flags &= ~I_D_DISK_ONLY; break; case 'd': flags |= I_D_DISK_ONLY; /* Display disk utilization only */ flags &= ~I_D_CPU_ONLY; break; case 'k': if (DISPLAY_MEGABYTES(flags)) usage(argv[0]); flags |= I_D_KILOBYTES; /* Display stats in kB/s */ break; case 'm': if (DISPLAY_KILOBYTES(flags)) usage(argv[0]); flags |= I_D_MEGABYTES; /* Display stats in MB/s */ break; case 't': flags |= I_D_TIMESTAMP; /* Display timestamp */ break; case 'x': flags |= I_D_EXTENDED; /* Display extended stats */ break; case 'V': /* Print version number and exit */ print_version(); break; default: usage(argv[0]); } } opt++; } else if (!isdigit(argv[opt][0])) { flags |= I_D_UNFILTERED; if (strcmp(argv[opt], K_ALL)) /* Store device name */ update_dev_list(&dlist_idx, device_name(argv[opt++])); else opt++; } else if (!it) { interval = atol(argv[opt++]); if (interval < 1) usage(argv[0]); count = -1; it = 1; } else { count = atol(argv[opt++]); if (count < 1) usage(argv[0]); } } /* Linux does not provide extended stats for partitions */ if (DISPLAY_PARTITIONS(flags) && DISPLAY_EXTENDED(flags)) { fprintf(stderr, _("-x and -p options are mutually exclusive\n")); exit(1); } /* Ignore device list if '-p ALL' entered on the command line */ if (DISPLAY_PART_ALL(flags)) dlist_idx = 0; /* Init structures according to machine architecture */ io_sys_init(&flags); get_localtime(&loc_time); /* Get system name, release number and hostname */ uname(&header); print_gal_header(&loc_time, header.sysname, header.release, header.nodename); printf("\n"); /* Set a handler for SIGALRM */ alarm_handler(0); /* Main loop */ rw_io_stat_loop(flags, count, &loc_time); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -