📄 iostat.c
字号:
sscanf(line + 10, "%lu %lu %lu %lu", &v_tmp[0], &v_tmp[1], &v_tmp[2], &v_tmp[3]); st_iodev_tmp[0]->dk_drive_rblk = v_tmp[0]; st_iodev_tmp[1]->dk_drive_rblk = v_tmp[1]; st_iodev_tmp[2]->dk_drive_rblk = v_tmp[2]; st_iodev_tmp[3]->dk_drive_rblk = v_tmp[3]; } else if (!strncmp(line, "disk_wblk ", 10)) { /* Read the number of blocks written to disk */ sscanf(line + 10, "%lu %lu %lu %lu", &v_tmp[0], &v_tmp[1], &v_tmp[2], &v_tmp[3]); st_iodev_tmp[0]->dk_drive_wblk = v_tmp[0]; st_iodev_tmp[1]->dk_drive_wblk = v_tmp[1]; st_iodev_tmp[2]->dk_drive_wblk = v_tmp[2]; st_iodev_tmp[3]->dk_drive_wblk = v_tmp[3]; } else if (!strncmp(line, "disk ", 5)) { /* Read the number of I/O done since the last reboot */ sscanf(line + 5, "%lu %lu %lu %lu", &v_tmp[0], &v_tmp[1], &v_tmp[2], &v_tmp[3]); st_iodev_tmp[0]->dk_drive = v_tmp[0]; st_iodev_tmp[1]->dk_drive = v_tmp[1]; st_iodev_tmp[2]->dk_drive = v_tmp[2]; st_iodev_tmp[3]->dk_drive = v_tmp[3]; } else if (!strncmp(line, "disk_io: ", 9)) { struct io_stats sdev; char dev_name[MAX_NAME_LEN]; pos = 9; /* Every disk_io entry is potentially unregistered */ set_entries_inactive(iodev_nr); /* Read disks I/O statistics (for 2.4 kernels) */ while (pos < strlen(line) - 1) { /* Beware: a CR is already included in the line */ sscanf(line + pos, "(%u,%u):(%lu,%*u,%lu,%*u,%lu) ", &v_major, &v_index, &v_tmp[0], &v_tmp[1], &v_tmp[2]); sprintf(dev_name, "dev%d-%d", v_major, v_index); sdev.dk_drive = v_tmp[0]; sdev.dk_drive_rblk = v_tmp[1]; sdev.dk_drive_wblk = v_tmp[2]; save_dev_stats(dev_name, curr, &sdev); pos += strcspn(line + pos, " ") + 1; } /* Free structures corresponding to unregistered disks */ free_inactive_entries(iodev_nr); } } fclose(fp);}/* *************************************************************************** * Read sysfs stat for current block device or partition *************************************************************************** */int read_sysfs_file_stat(int curr, char *filename, char *dev_name, int dev_type){ FILE *fp; struct io_stats sdev; int i; /* Try to read given stat file */ if ((fp = fopen(filename, "r")) == NULL) return 0; if (dev_type == DT_DEVICE) i = (fscanf(fp, "%lu %lu %llu %lu %lu %lu %llu %lu %lu %lu %lu", &sdev.rd_ios, &sdev.rd_merges, &sdev.rd_sectors, &sdev.rd_ticks, &sdev.wr_ios, &sdev.wr_merges, &sdev.wr_sectors, &sdev.wr_ticks, &sdev.ios_pgr, &sdev.tot_ticks, &sdev.rq_ticks) == 11); else i = (fscanf(fp, "%lu %llu %lu %llu", &sdev.rd_ios, &sdev.rd_sectors, &sdev.wr_ios, &sdev.wr_sectors) == 4); if (i) save_dev_stats(dev_name, curr, &sdev); fclose(fp); return 1;}/* *************************************************************************** * Read sysfs stats for all the partitions of a device *************************************************************************** */void read_sysfs_dlist_part_stat(int curr, char *dev_name){ DIR *dir; struct dirent *drd; char dfile[MAX_PF_NAME], filename[MAX_PF_NAME]; sprintf(dfile, "%s/%s", SYSFS_BLOCK, dev_name); /* Open current device directory in /sys/block */ if ((dir = opendir(dfile)) == NULL) return; /* Get current entry */ while ((drd = readdir(dir)) != NULL) { if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, "..")) continue; sprintf(filename, "%s/%s/%s", dfile, drd->d_name, S_STAT); /* Read current partition stats */ read_sysfs_file_stat(curr, filename, drd->d_name, DT_PARTITION); } /* Close device directory */ closedir(dir);}/* *************************************************************************** * Read stats from the sysfs filesystem * for the devices entered on the command line *************************************************************************** */void read_sysfs_dlist_stat(int curr, int flags){ int dev, ok; char filename[MAX_PF_NAME]; struct io_dlist *st_dev_list_i; /* Every I/O device (or partition) is potentially unregistered */ set_entries_inactive(iodev_nr); for (dev = 0; dev < dlist_idx; dev++) { st_dev_list_i = st_dev_list + dev; sprintf(filename, "%s/%s/%s", SYSFS_BLOCK, st_dev_list_i->dev_name, S_STAT); /* Read device stats */ ok = read_sysfs_file_stat(curr, filename, st_dev_list_i->dev_name, DT_DEVICE); if (ok && st_dev_list_i->disp_part) /* Also read stats for its partitions */ read_sysfs_dlist_part_stat(curr, st_dev_list_i->dev_name); } /* Free structures corresponding to unregistered devices */ free_inactive_entries(iodev_nr);}/* *************************************************************************** * Read stats from the sysfs filesystem * for every block devices found *************************************************************************** */void read_sysfs_stat(int curr, int flags){ DIR *dir; struct dirent *drd; char filename[MAX_PF_NAME]; int ok; /* Every I/O device entry is potentially unregistered */ set_entries_inactive(iodev_nr); /* Open /sys/block directory */ if ((dir = opendir(SYSFS_BLOCK)) != NULL) { /* Get current entry */ while ((drd = readdir(dir)) != NULL) { if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, "..")) continue; sprintf(filename, "%s/%s/%s", SYSFS_BLOCK, drd->d_name, S_STAT); /* If current entry is a directory, try to read its stat file */ ok = read_sysfs_file_stat(curr, filename, drd->d_name, DT_DEVICE); /* * If '-p ALL' was entered on the command line, * also try to read stats for its partitions */ if (ok && DISPLAY_PART_ALL(flags)) read_sysfs_dlist_part_stat(curr, drd->d_name); } /* Close /sys/block directory */ closedir(dir); } /* Free structures corresponding to unregistered devices */ free_inactive_entries(iodev_nr);}/* *************************************************************************** * Read stats from /proc/diskstats *************************************************************************** */void read_diskstats_stat(int curr, int flags){ FILE *fp; char line[256], dev_name[MAX_NAME_LEN]; struct io_stats sdev; int i; unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios; unsigned long ios_pgr, tot_ticks, rq_ticks, wr_merges, wr_ticks; unsigned long long rd_sec_or_wr_ios, wr_sec; char *ioc_dname; unsigned int major, minor; /* Every I/O device entry is potentially unregistered */ set_entries_inactive(iodev_nr); if ((fp = fopen(DISKSTATS, "r")) == NULL) return; while (fgets(line, 256, fp) != NULL) { /* major minor name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq */ i = sscanf(line, "%u %u %s %lu %lu %llu %lu %lu %lu %llu %lu %lu %lu %lu", &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); if (i == 14) { /* Device */ sdev.rd_ios = rd_ios; sdev.rd_merges = rd_merges_or_rd_sec; sdev.rd_sectors = rd_sec_or_wr_ios; sdev.rd_ticks = rd_ticks_or_wr_sec; sdev.wr_ios = wr_ios; sdev.wr_merges = wr_merges; sdev.wr_sectors = wr_sec; sdev.wr_ticks = wr_ticks; sdev.ios_pgr = ios_pgr; sdev.tot_ticks = tot_ticks; sdev.rq_ticks = rq_ticks; } else if (i == 7) { /* Partition */ if (DISPLAY_EXTENDED(flags) || (!dlist_idx && !DISPLAY_PARTITIONS(flags))) continue; sdev.rd_ios = rd_ios; sdev.rd_sectors = rd_merges_or_rd_sec; sdev.wr_ios = rd_sec_or_wr_ios; sdev.wr_sectors = rd_ticks_or_wr_sec; } else /* Unknown entry: ignore it */ continue; if ((ioc_dname = ioc_name(major, minor)) != NULL) { if (strcmp(dev_name, ioc_dname) && strcmp(ioc_dname, K_NODEV)) /* * No match: Use name generated from sysstat.ioconf data (if different * from "nodev") works around known issues with EMC PowerPath. */ strcpy(dev_name, ioc_dname); } save_dev_stats(dev_name, curr, &sdev); } fclose(fp); /* Free structures corresponding to unregistered devices */ free_inactive_entries(iodev_nr);}/* *************************************************************************** * Read stats from /proc/partitions *************************************************************************** */void read_ppartitions_stat(int curr, int flags){ FILE *fp; char line[256], dev_name[MAX_NAME_LEN]; struct io_stats sdev; unsigned long rd_ios, rd_merges, rd_ticks, wr_ios, wr_merges, wr_ticks; unsigned long ios_pgr, tot_ticks, rq_ticks; unsigned long long rd_sec, wr_sec; char *ioc_dname; unsigned int major, minor; /* Every I/O device entry is potentially unregistered */ set_entries_inactive(iodev_nr); if ((fp = fopen(PPARTITIONS, "r")) == NULL) return; while (fgets(line, 256, fp) != NULL) { /* major minor #blocks name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq */ if (sscanf(line, "%u %u %*u %s %lu %lu %llu %lu %lu %lu %llu" " %lu %lu %lu %lu", &major, &minor, dev_name, &rd_ios, &rd_merges, &rd_sec, &rd_ticks, &wr_ios, &wr_merges, &wr_sec, &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks) == 14) { /* Device or partition */ sdev.rd_ios = rd_ios; sdev.rd_merges = rd_merges; sdev.rd_sectors = rd_sec; sdev.rd_ticks = rd_ticks; sdev.wr_ios = wr_ios; sdev.wr_merges = wr_merges; sdev.wr_sectors = wr_sec; sdev.wr_ticks = wr_ticks; sdev.ios_pgr = ios_pgr; sdev.tot_ticks = tot_ticks; sdev.rq_ticks = rq_ticks; } else /* Unknown entry: ignore it */ continue; if ((ioc_dname = ioc_name(major, minor)) != NULL) { if (strcmp(dev_name, ioc_dname) && strcmp(ioc_dname, K_NODEV)) /* Compensate for EMC PowerPath driver bug */ strcpy(dev_name, ioc_dname); } save_dev_stats(dev_name, curr, &sdev); } fclose(fp); /* Free structures corresponding to unregistered devices */ free_inactive_entries(iodev_nr);}/* *************************************************************************** * Display CPU utilization *************************************************************************** */void write_cpu_stat(int curr, unsigned long long itv){ printf("avg-cpu: %%user %%nice %%system %%iowait %%steal %%idle\n"); printf(" %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n\n", ll_sp_value(comm_stats[!curr].cpu_user, comm_stats[curr].cpu_user, itv), ll_sp_value(comm_stats[!curr].cpu_nice, comm_stats[curr].cpu_nice, itv), ll_sp_value(comm_stats[!curr].cpu_system, comm_stats[curr].cpu_system, itv), ll_sp_value(comm_stats[!curr].cpu_iowait, comm_stats[curr].cpu_iowait, itv), ll_sp_value(comm_stats[!curr].cpu_steal, comm_stats[curr].cpu_steal, itv), (comm_stats[curr].cpu_idle < comm_stats[!curr].cpu_idle) ? 0.0 : ll_sp_value(comm_stats[!curr].cpu_idle, comm_stats[curr].cpu_idle, itv));}/* *************************************************************************** * Display stats header *************************************************************************** */void write_stat_header(int flags, int *fctr){ if (DISPLAY_EXTENDED(flags)) { /* Extended stats */ printf("Device: rrqm/s wrqm/s r/s w/s"); if (DISPLAY_MEGABYTES(flags)) { printf(" rMB/s wMB/s"); *fctr = 2048; } else if (DISPLAY_KILOBYTES(flags)) { printf(" rkB/s wkB/s"); *fctr = 2; } else printf(" rsec/s wsec/s"); printf(" avgrq-sz avgqu-sz await svctm %%util\n"); } else { /* Basic stats */ printf("Device: tps"); if (DISPLAY_KILOBYTES(flags)) { printf(" kB_read/s kB_wrtn/s kB_read kB_wrtn\n"); *fctr = 2; } else if (DISPLAY_MEGABYTES(flags)) { printf(" MB_read/s MB_wrtn/s MB_read MB_wrtn\n"); *fctr = 2048; } else printf(" Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn\n"); }}/* *************************************************************************** * Display extended stats, read from /proc/{diskstats,partitions} or /sys *************************************************************************** */void write_ext_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; double tput, util, await, svctm, arqsz, nr_ios; /* * Counters overflows are possible, but don't need to be handled in * a special way: the difference is still properly calculated if the * result is of the same type as the two values. * Exception is field rq_ticks which is incremented by the number of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -