sadf.c
来自「linux下查看系统工具原码,如IOSTAT等」· C语言 代码 · 共 2,002 行 · 第 1/4 页
C
2,002 行
/* *************************************************************************** * Read varying part of the statistics from a daily data file *************************************************************************** */void read_extra_stats(short curr, int ifd){ if (file_hdr.sa_proc > 0) sa_fread(ifd, st_cpu[curr], STATS_ONE_CPU_SIZE * (file_hdr.sa_proc + 1), HARD_SIZE); if (GET_ONE_IRQ(file_hdr.sa_actflag)) sa_fread(ifd, interrupts[curr], STATS_ONE_IRQ_SIZE, HARD_SIZE); if (file_hdr.sa_serial) sa_fread(ifd, st_serial[curr], STATS_SERIAL_SIZE * file_hdr.sa_serial, HARD_SIZE); if (file_hdr.sa_irqcpu) sa_fread(ifd, st_irq_cpu[curr], STATS_IRQ_CPU_SIZE * (file_hdr.sa_proc + 1) * file_hdr.sa_irqcpu, HARD_SIZE); if (file_hdr.sa_iface) sa_fread(ifd, st_net_dev[curr], STATS_NET_DEV_SIZE * file_hdr.sa_iface, HARD_SIZE); if (file_hdr.sa_nr_disk) sa_fread(ifd, st_disk[curr], DISK_STATS_SIZE * file_hdr.sa_nr_disk, HARD_SIZE); /* PID stats cannot be saved in file. So we don't read them */}/* *************************************************************************** * Read stats for current activity from file *************************************************************************** */void read_curr_act_stats(int ifd, off_t fpos, short *curr, long *cnt, int *eosaf, unsigned int act, int *reset){ unsigned char rtype; int next; if (lseek(ifd, fpos, SEEK_SET) < fpos) { perror("lseek"); exit(2); } /* * Restore the first stats collected. * Used to compute the rate displayed on the first line. */ copy_structures(!(*curr), 2); *cnt = count; do { /* Display <count> lines of stats */ *eosaf = sa_fread(ifd, &file_stats[*curr], file_hdr.sa_st_size, SOFT_SIZE); rtype = file_stats[*curr].record_type; if (!(*eosaf) && (rtype != R_DUMMY)) { /* Read the extra fields since it's not a DUMMY record */ read_extra_stats(*curr, ifd); next = write_parsable_stats(*curr, act, *reset, cnt, tm_start.use, tm_end.use); if (next) { /* * next is set to 1 when we were close enough to desired interval. * In this case, the call to write_parsable_stats() has actually * displayed a line of stats. */ *curr ^=1; if ((*cnt) > 0) (*cnt)--; } *reset = FALSE; } } while ((*cnt) && !(*eosaf) && (rtype != R_DUMMY)); *reset = TRUE;}/* *************************************************************************** * Display activities for -x option *************************************************************************** */void xml_display_loop(int ifd){ unsigned char rtype; short curr, tab = 0; int eosaf = TRUE; off_t fpos; /* Save current file position */ if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) { perror("lseek"); exit(2); } /* Print XML header */ display_xml_header(&tab); xprintf(tab, "<statistics>"); /* Process activities */ tab++; do { /* If this record is a DUMMY one, try to get another one */ do { eosaf = sa_fread(ifd, &file_stats[0], file_hdr.sa_st_size, SOFT_SIZE); rtype = file_stats[0].record_type; if (!eosaf && (rtype != R_DUMMY)) { /* * Ok: previous record was not a DUMMY one. * So read now the extra fields. */ read_extra_stats(0, ifd); } } while (!eosaf && (rtype == R_DUMMY)); curr = 1; if (!eosaf) { do { eosaf = sa_fread(ifd, &file_stats[curr], file_hdr.sa_st_size, SOFT_SIZE); rtype = file_stats[curr].record_type; if (!eosaf && (rtype != R_DUMMY)) { /* Read the extra fields since it's not a DUMMY record */ read_extra_stats(curr, ifd); write_xml_stats(curr, &tab); curr ^= 1; } } while (!eosaf && (rtype != R_DUMMY)); } } while (!eosaf); /* Rewind file */ if (lseek(ifd, fpos, SEEK_SET) < fpos) { perror("lseek"); exit(2); } xprintf(--tab, "</statistics>"); xprintf(tab, "<restarts>"); /* Process now DUMMY entries to display restart messages */ tab++; do { if ((eosaf = sa_fread(ifd, &file_stats[0], file_hdr.sa_st_size, SOFT_SIZE)) == 0) { if (file_stats[0].record_type != R_DUMMY) read_extra_stats(0, ifd); else write_xml_restarts(0, &tab); } } while (!eosaf); xprintf(--tab, "</restarts>"); xprintf(--tab, "</host>"); xprintf(--tab, "</sysstat>");}/* *************************************************************************** * Display activities for -p and -d options *************************************************************************** */void main_display_loop(int ifd){ short curr = 1; unsigned int act; int eosaf = TRUE, reset = FALSE; long cnt = 1; off_t fpos; /* Read system statistics from file */ do { /* * If this record is a DUMMY one, print it and (try to) get another one. * We must be sure that we have real stats in file_stats[2]. */ do { if (sa_fread(ifd, &file_stats[0], file_hdr.sa_st_size, SOFT_SIZE)) /* End of sa data file */ return; if (file_stats[0].record_type == R_DUMMY) write_dummy(0, tm_start.use, tm_end.use); else { /* Ok: previous record was not a DUMMY one. So read now the extra fields. */ read_extra_stats(0, ifd); set_loc_time(0); } } while ((file_stats[0].record_type == R_DUMMY) || (tm_start.use && (datecmp(&loc_time, &tm_start) < 0)) || (tm_end.use && (datecmp(&loc_time, &tm_end) >=0))); /* Save the first stats collected. Will be used to compute the average */ copy_structures(2, 0); reset = TRUE; /* Set flag to reset last_uptime variable */ /* Save current file position */ if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) { perror("lseek"); exit(2); } /* Read and write stats located between two possible Linux restarts */ /* For each requested activity... */ for (act = 1; act <= A_LAST; act <<= 1) { if (sadf_actflag & act) { if ((act == A_IRQ) && WANT_PER_PROC(flags) && WANT_ALL_PROC(flags)) { /* Distinguish -I SUM activity from IRQs per processor activity */ flags &= ~S_F_PER_PROC; read_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, act, &reset); flags |= S_F_PER_PROC; flags &= ~S_F_ALL_PROC; read_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, act, &reset); flags |= S_F_ALL_PROC; } else read_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, act, &reset); } } if (!cnt) { /* Go to next Linux restart, if possible */ do { eosaf = sa_fread(ifd, &file_stats[curr], file_hdr.sa_st_size, SOFT_SIZE); if (!eosaf && (file_stats[curr].record_type != R_DUMMY)) read_extra_stats(curr, ifd); } while (!eosaf && (file_stats[curr].record_type != R_DUMMY)); } /* The last record we read was a DUMMY one: print it */ if (!eosaf && (file_stats[curr].record_type == R_DUMMY)) write_dummy(curr, tm_start.use, tm_end.use); } while (!eosaf);}/* *************************************************************************** * Read statistics from a system activity data file *************************************************************************** */void read_stats_from_file(char dfile[]){ int ifd; /* Prepare file for reading */ prep_file_for_reading(&ifd, dfile, &file_hdr, &sadf_actflag, flags); if (format == S_O_HDR_OPTION) { /* Display data file header */ display_file_header(dfile, &file_hdr); return; } /* Perform required allocations */ allocate_structures(USE_SA_FILE); /* Print report header if needed */ print_report_hdr(format, flags, &loc_time, &file_hdr); if (format == S_O_XML_OPTION) xml_display_loop(ifd); else main_display_loop(ifd); close(ifd);}/* *************************************************************************** * Main entry to the sadf program *************************************************************************** */int main(int argc, char **argv){ int opt = 1, sar_options = 0; int i; char dfile[MAX_FILE_LEN]; short dum; /* Compute page shift in kB */ kb_shift = get_kb_shift(); dfile[0] = '\0';#ifdef USE_NLS /* Init National Language Support */ init_nls();#endif tm_start.use = tm_end.use = FALSE; init_bitmap(irq_bitmap, 0, NR_IRQS); init_bitmap(cpu_bitmap, 0, NR_CPUS); init_stats(file_stats, interrupts); /* Process options */ while (opt < argc) { if (!strcmp(argv[opt], "-I")) { if (argv[++opt] && sar_options) { if (parse_sar_I_opt(argv, &opt, &sadf_actflag, &dum, irq_bitmap)) usage(argv[0]); } else usage(argv[0]); } else if (!strcmp(argv[opt], "-P")) { if (parse_sa_P_opt(argv, &opt, &flags, &dum, cpu_bitmap)) usage(argv[0]); } else if (!strcmp(argv[opt], "-s")) { /* Get time start */ if (parse_timestamp(argv, &opt, &tm_start, DEF_TMSTART)) usage(argv[0]); } else if (!strcmp(argv[opt], "-e")) { /* Get time end */ if (parse_timestamp(argv, &opt, &tm_end, DEF_TMEND)) usage(argv[0]); } else if (!strcmp(argv[opt], "--")) { sar_options = 1; opt++; } else if (!strcmp(argv[opt], "-n")) { if (argv[++opt] && sar_options) { /* Parse sar's option -n */ if (parse_sar_n_opt(argv, &opt, &sadf_actflag, &dum)) usage(argv[0]); } else usage(argv[0]); } else if (!strncmp(argv[opt], "-", 1)) { /* Other options not previously tested */ if (sar_options) { if (parse_sar_opt(argv, opt, &sadf_actflag, &flags, &dum, C_SADF, irq_bitmap, cpu_bitmap)) usage(argv[0]); } else { for (i = 1; *(argv[opt] + i); i++) { switch (*(argv[opt] + i)) { case 'd': if (format && (format != S_O_DB_OPTION)) usage(argv[0]); format = S_O_DB_OPTION; break; case 'H': if (format && (format != S_O_HDR_OPTION)) usage(argv[0]); format = S_O_HDR_OPTION; break; case 'p': if (format && (format != S_O_PPC_OPTION)) usage(argv[0]); format = S_O_PPC_OPTION; break; case 't': flags |= S_F_TRUE_TIME; break; case 'x': if (format && (format != S_O_XML_OPTION)) usage(argv[0]); format = S_O_XML_OPTION; break; case 'V': print_version(); break; default: usage(argv[0]); } } } opt++; } /* Get data file name */ else if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) { if (!dfile[0]) { if (!strcmp(argv[opt], "-")) { /* File name set to '-' */ get_localtime(&loc_time); snprintf(dfile, MAX_FILE_LEN, "%s/sa%02d", SA_DIR, loc_time.tm_mday); dfile[MAX_FILE_LEN - 1] = '\0'; opt++; } else if (!strncmp(argv[opt], "-", 1)) /* Bad option */ usage(argv[0]); else { /* Write data to file */ strncpy(dfile, argv[opt++], MAX_FILE_LEN); dfile[MAX_FILE_LEN - 1] = '\0'; } } else /* File already specified */ usage(argv[0]); } else if (interval < 0) { /* Get interval */ if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) usage(argv[0]); interval = atol(argv[opt++]); if (interval <= 0) usage(argv[0]); } else { /* Get count value */ if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) usage(argv[0]); if (count) /* Count parameter already set */ usage(argv[0]); count = atol(argv[opt++]); if (count < 0) usage(argv[0]); else if (!count) count = -1; /* To generate a report continuously */ } } /* sadf reads current daily data file by default */ if (!dfile[0]) { get_localtime(&loc_time); snprintf(dfile, MAX_FILE_LEN, "%s/sa%02d", SA_DIR, loc_time.tm_mday); dfile[MAX_FILE_LEN - 1] = '\0'; } /* * Display all the contents of the daily data file if the count parameter * was not set on the command line. */ if (!count) count = -1; /* * Default is CPU activity and PPC display. * For XML display, activity flag is meaningless since every activity will * be displayed. So make sure that sadf won't complain about non existent * activities in file... */ if (!sadf_actflag || (format == S_O_XML_OPTION)) sadf_actflag |= A_CPU; if (!format) format = S_O_PPC_OPTION; if (interval < 0) interval = 1; /* Read stats from file */ read_stats_from_file(dfile); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?