📄 sar.c
字号:
fsi->tlskb - fsi->frskb, fsi->tlskb ? SP_VALUE(fsi->frskb, fsi->tlskb, fsi->tlskb) : 0.0, fsi->caskb); /* * Will be used to compute the average. * Note: overflow unlikely to happen but not impossible... * We assume that the total amount of memory installed can not vary * during the interval given on the command line, whereas the total * amount of swap space may. */ asum.frmkb += fsi->frmkb; asum.bufkb += fsi->bufkb; asum.camkb += fsi->camkb; asum.frskb += fsi->frskb; asum.tlskb += fsi->tlskb; asum.caskb += fsi->caskb; } /* Print values of some kernel tables */ if (GET_KTABLES(act)) { if (dis) printf("\n%-11s dentunusd file-sz inode-sz super-sz %%super-sz " "dquot-sz %%dquot-sz rtsig-sz %%rtsig-sz\n", cur_time[!curr]); printf("%-11s %9u %9u %9u %9u %6.2f %9u %6.2f %9u %6.2f\n", cur_time[curr], fsi->dentry_stat, fsi->file_used, fsi->inode_used, fsi->super_used, fsi->super_max ? ((double) (fsi->super_used * 100)) / fsi->super_max : 0.0, fsi->dquot_used, fsi->dquot_max ? ((double) (fsi->dquot_used * 100)) / fsi->dquot_max : 0.0, fsi->rtsig_queued, fsi->rtsig_max ? ((double) (fsi->rtsig_queued * 100)) / fsi->rtsig_max : 0.0); /* * Will be used to compute the average. * Note: overflow unlikely to happen but not impossible... * We assume that *_max values can not vary during the interval. */ asum.dentry_stat += fsi->dentry_stat; asum.file_used += fsi->file_used; asum.inode_used += fsi->inode_used; asum.super_used += fsi->super_used; asum.dquot_used += fsi->dquot_used; asum.rtsig_queued += fsi->rtsig_queued; } /* Print number of sockets in use */ if (GET_NET_SOCK(act)) { if (dis) printf("\n%-11s totsck tcpsck udpsck rawsck ip-frag\n", cur_time[!curr]); printf("%-11s %9u %9u %9u %9u %9u\n", cur_time[curr], fsi->sock_inuse, fsi->tcp_inuse, fsi->udp_inuse, fsi->raw_inuse, fsi->frag_inuse); /* Will be used to compute the average */ asum.sock_inuse += fsi->sock_inuse; asum.tcp_inuse += fsi->tcp_inuse; asum.udp_inuse += fsi->udp_inuse; asum.raw_inuse += fsi->raw_inuse; asum.frag_inuse += fsi->frag_inuse; } /* Print load averages and queue length */ if (GET_QUEUE(act)) { if (dis) printf("\n%-11s runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15\n", cur_time[!curr]); printf("%-11s %9lu %9u %9.2f %9.2f %9.2f\n", cur_time[curr], fsi->nr_running, fsi->nr_threads, (double) fsi->load_avg_1 / 100, (double) fsi->load_avg_5 / 100, (double) fsi->load_avg_15 / 100); /* Will be used to compute the average */ asum.nr_running += fsi->nr_running; asum.nr_threads += fsi->nr_threads; asum.load_avg_1 += fsi->load_avg_1; asum.load_avg_5 += fsi->load_avg_5; asum.load_avg_15 += fsi->load_avg_15; } return 1;}/* *************************************************************************** * Display stats since system startup *************************************************************************** */void write_stats_startup(short curr){ /* Set to 0 previous structures corresponding to boot time */ memset(&file_stats[!curr], 0, FILE_STATS_SIZE); file_stats[!curr].record_type = R_STATS; file_stats[!curr].hour = file_stats[curr].hour; file_stats[!curr].minute = file_stats[curr].minute; file_stats[!curr].second = file_stats[curr].second; file_stats[!curr].ust_time = file_stats[curr].ust_time; if (file_hdr.sa_proc > 0) memset(st_cpu[!curr], 0, STATS_ONE_CPU_SIZE * (file_hdr.sa_proc + 1)); memset(interrupts[!curr], 0, STATS_ONE_IRQ_SIZE); if (pid_nr) memset (pid_stats[!curr][0], 0, PID_STATS_SIZE * pid_nr); if (file_hdr.sa_serial) memset(st_serial[!curr], 0, STATS_SERIAL_SIZE * file_hdr.sa_serial); if (file_hdr.sa_irqcpu) memset(st_irq_cpu[!curr], 0, STATS_IRQ_CPU_SIZE * (file_hdr.sa_proc + 1) * file_hdr.sa_irqcpu); if (file_hdr.sa_iface) memset(st_net_dev[!curr], 0, STATS_NET_DEV_SIZE * file_hdr.sa_iface); if (file_hdr.sa_nr_disk) memset(st_disk[!curr], 0, DISK_STATS_SIZE * file_hdr.sa_nr_disk); /* Display stats since boot time */ write_stats(curr, DISP_HDR, sar_actflag, USE_SADC, &count, NO_TM_START, NO_TM_END, NO_RESET, ST_SINCE_BOOT); exit(0); }/* *************************************************************************** * Read data sent by the data collector *************************************************************************** */int sa_read(void *buffer, int size){ int n; while (size) { if ((n = read(STDIN_FILENO, buffer, size)) < 0) { perror("read"); exit(2); } if (!n) return 1; /* EOF */ size -= n; buffer = (char *) buffer + n; } return 0;}/* *************************************************************************** * Print a Linux restart message (contents of a DUMMY record) *************************************************************************** */void write_dummy(short curr, int use_tm_start, int use_tm_end){ char cur_time[26]; set_timestamp(curr, cur_time, 26); /* The RESTART message must be in the interval specified by -s/-e options */ if ((use_tm_start && (datecmp(&loc_time, &tm_start) < 0)) || (use_tm_end && (datecmp(&loc_time, &tm_end) > 0))) return; printf("\n%-11s LINUX RESTART\n", cur_time);}/* *************************************************************************** * Move structures data *************************************************************************** */void copy_structures(int dest, int src, int stype){ memcpy(&file_stats[dest], &file_stats[src], FILE_STATS_SIZE); if (file_hdr.sa_proc > 0) memcpy(st_cpu[dest], st_cpu[src], STATS_ONE_CPU_SIZE * (file_hdr.sa_proc + 1)); if (GET_ONE_IRQ(file_hdr.sa_actflag)) memcpy(interrupts[dest], interrupts[src], STATS_ONE_IRQ_SIZE); if ((stype == USE_SADC) && (pid_nr)) memcpy(pid_stats[dest][0], pid_stats[src][0], PID_STATS_SIZE * pid_nr); if (file_hdr.sa_serial) memcpy(st_serial[dest], st_serial[src], STATS_SERIAL_SIZE * file_hdr.sa_serial); if (file_hdr.sa_irqcpu) memcpy(st_irq_cpu[dest], st_irq_cpu[src], STATS_IRQ_CPU_SIZE * (file_hdr.sa_proc + 1) * file_hdr.sa_irqcpu); if (file_hdr.sa_iface) memcpy(st_net_dev[dest], st_net_dev[src], STATS_NET_DEV_SIZE * file_hdr.sa_iface); if (file_hdr.sa_nr_disk) memcpy(st_disk[dest], st_disk[src], DISK_STATS_SIZE * file_hdr.sa_nr_disk);}/* *************************************************************************** * 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 a bunch of statistics sent by the data collector *************************************************************************** */void read_stat_bunch(short curr){ if (sa_read(&file_stats[curr], file_hdr.sa_st_size)) exit(0); if ((file_hdr.sa_proc > 0) && sa_read(st_cpu[curr], STATS_ONE_CPU_SIZE * (file_hdr.sa_proc + 1))) exit(0); if (GET_ONE_IRQ(file_hdr.sa_actflag) && sa_read(interrupts[curr], STATS_ONE_IRQ_SIZE)) exit(0); if (pid_nr && sa_read(pid_stats[curr][0], PID_STATS_SIZE * pid_nr)) exit(0); if (file_hdr.sa_serial && sa_read(st_serial[curr], STATS_SERIAL_SIZE * file_hdr.sa_serial)) exit(0); if (file_hdr.sa_irqcpu && sa_read(st_irq_cpu[curr], STATS_IRQ_CPU_SIZE * (file_hdr.sa_proc + 1) * file_hdr.sa_irqcpu)) exit(0); if (file_hdr.sa_iface && sa_read(st_net_dev[curr], STATS_NET_DEV_SIZE * file_hdr.sa_iface)) exit(0); if (file_hdr.sa_nr_disk && sa_read(st_disk[curr], DISK_STATS_SIZE * file_hdr.sa_nr_disk)) exit(0);}/* *************************************************************************** * Read stats for current activity from file and display them. *************************************************************************** */void handle_curr_act_stats(int ifd, off_t fpos, short *curr, long *cnt, int *eosaf, int rows, unsigned int act, int *reset){ short dis = 1; unsigned long lines; unsigned char rtype; int davg, 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, USE_SA_FILE); lines = 0; davg = 0; *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); dis = !(lines++ % rows); if (!(*eosaf) && (rtype != R_DUMMY)) { /* next is set to 1 when we were close enough to desired interval */ next = write_stats(*curr, dis, act, USE_SA_FILE, cnt, tm_start.use, tm_end.use, *reset, ST_IMMEDIATE); if (next && ((*cnt) > 0)) (*cnt)--; if (next) { davg++; *curr ^=1; } else lines--; *reset = 0; } } while ((*cnt) && !(*eosaf) && (rtype != R_DUMMY)); if (davg) write_stats_avg(!(*curr), dis, act, USE_SA_FILE); *reset = TRUE;}/* *************************************************************************** * Read header data sent by sadc *************************************************************************** */void read_header_data(void){ /* Read stats header */ if (sa_read(&file_hdr, FILE_HDR_SIZE)) exit(0); if (file_hdr.sa_magic != SA_MAGIC) { /* sar and sadc commands are not consistent */ fprintf(stderr, _("Invalid data format\n")); exit(3); }}/* *************************************************************************** * Read statistics from a system activity data file *************************************************************************** */void read_stats_from_file(char from_file[]){ short curr = 1; unsigned int act; int ifd; int rows = 23, eosaf = TRUE, reset = FALSE; long cnt = 1; off_t fpos; if (!dis_hdr) /* Get window size */ rows = get_win_height(); /* Prepare file for reading */ prep_file_for_reading(&ifd, from_file, &file_hdr, &sar_actflag, flags); if ((GET_SERIAL(sar_actflag) && (file_hdr.sa_serial > 1)) || ((GET_NET_DEV(sar_actflag) || GET_NET_EDEV(sar_actflag)) && (file_hdr.sa_iface > 1)) || (GET_DISK(sar_actflag) && (file_hdr.sa_nr_disk > 1))) dis_hdr = 9; /* Perform required allocations */ allocate_structures(USE_SA_FILE); /* Print report header */ print_report_hdr(S_O_NONE, flags, &loc_time, &file_hdr); /* 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, USE_SA_FILE); 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 (sar_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; handle_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, rows, act, &reset); flags |= S_F_PER_PROC; flags &= ~S_F_ALL_PROC; handle_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, rows, act, &reset); flags |= S_F_ALL_PROC; } else handle_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, rows, 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -