📄 perfmon.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)perfmon.c 1.1 92/07/30";#endif#endif/* * Copyright (c) 1986 by Sun Microsystems, Inc. *//* * Simple graphical performance monitor for system-wide data. */#include <stdio.h>#include <strings.h> /* ************* \/ vmstat \/ *************** */#include <sys/param.h>#include <sys/vm.h>#include <sys/dk.h>#include <nlist.h>#include <sys/buf.h>#include <sundev/mbvar.h> /* ************** ^ vmstat ^ **************** */ /* *********** \/ netstat/if.c \/ ************* */#include <sys/socket.h>#include <net/if.h>#include <netinet/in.h> /* ************ ^ netstat/if.c ^ ************** *//* param.h already does ... #include <sys/types.h> */#include <sys/file.h>#include <sys/time.h>#include <sys/types.h>#include <pixrect/pixrect.h>#include <pixrect/pixfont.h>#include <pixrect/pr_util.h>#include <pixrect/memvar.h>#include <sunwindow/rect.h>#include <sunwindow/rectlist.h>#include <sunwindow/pixwin.h>#include <sunwindow/win_input.h>#include <sunwindow/win_struct.h>#include <suntool/gfxsw.h>#define USEC_INC 50000#define SEC_INC 1struct packet { int input, output, collisions};static struct packet packets, old_packets;#define NUM_VALS_PER 1000struct statistic { int min_val, max_val; int value[NUM_VALS_PER]; char *label, *label2;};#define SECS_PER_TIME_TICK 15static char do_time[NUM_VALS_PER];static struct timeval current_time, saved_time;/* * The array stats always has valid info for stats[i], 0 <= i < num_stats. * For each valid stats[i], stats[i].value[j] is valid for 0 <= j < num_of_val. * The info for the k-th possible statistic of interest is recorded, if it is * recorded at all, in stats[possible_stats[k]]. */#define NO_STAT -1#define USER_CPU_PERCENTAGE 0#define SYSTEM_CPU_PERCENTAGE 1#define IDLE_CPU_PERCENTAGE 2#define FREE_MEM 3#define DISK_TRANSFERS 4#define INTERRUPTS 5#define INPUT_PACKETS 6#define OUTPUT_PACKETS 7#define COLLISION_PACKETS 8#define NUM_POSSIBLE_STATS 9static int possible_stats[NUM_POSSIBLE_STATS];#define WANT_STAT(x) (possible_stats[(x)] != NO_STAT)#define MAX_STATS 10static struct statistic *stats;static struct timeval timeout = {SEC_INC,USEC_INC}, timeleft;static struct gfxsubwindow *gfx;static int num_stats, num_of_val = 0, quit = 0, shift_left_on_new_cycle = -1;static int graph_x_offset = 0;static struct rect rect;static struct pixfont *font;#define FORALLPOSSIBLESTATS(stat) \ for (stat = 0; stat < NUM_POSSIBLE_STATS; stat++)#define FORALLSTATS(stat) \ for (stat = 0; stat < num_stats; stat++) /* ************* \/ vmstat \/ *************** */struct nlist nl[] = {#define X_CPTIME 0 { "_cp_time" },#define X_RATE 1 { "_rate" },#define X_TOTAL 2 { "_total" },#define X_DEFICIT 3 { "_deficit" },#define X_FORKSTAT 4 { "_forkstat" },#define X_SUM 5 { "_sum" },#define X_FIRSTFREE 6 { "_firstfree" },#define X_MAXFREE 7 { "_maxfree" },#define X_BOOTTIME 8 { "_boottime" },#define X_DKXFER 9 { "_dk_xfer" },#define X_REC 10 { "_rectime" },#define X_PGIN 11 { "_pgintime" },#define X_HZ 12 { "_hz" },#define X_MBDINIT 13 { "_mbdinit" },#define N_IFNET 14 { "_ifnet" }, /* ******** <-- netstat/if.c ******** */ { "" },};char *sprintf(), *strcpy();long lseek();char dr_name[DK_NDRIVE][10];char dr_unit[DK_NDRIVE];double stat1();int firstfree, maxfree;int hz;struct{ int busy; long time[CPUSTATES]; long xfer[DK_NDRIVE]; struct vmmeter Rate; struct vmtotal Total; struct vmmeter Sum; struct forkstat Forkstat; unsigned rectime; unsigned pgintime;} s, s1, z;#define rate s.Rate#define total s.Total#define sum s.Sum#define forkstat s.Forkstatstruct vmmeter osum;int zero;int deficit;double etime;int mf;int swflag;int nintv;double f1, f2;long t;#define steal(where, var) \ (void)lseek(mf, (long)where, 0); (void)read(mf, (char *)(LINT_CAST(&var)), sizeof var);#define pgtok(a) ((a)*NBPG/1024) /* ************** ^ vmstat ^ **************** */char *options[NUM_POSSIBLE_STATS+1] = { "user", "system", "idle", "free", "disk", "interrupts", "input", "output", "collision", 0 /* Terminator! */ };#ifdef STANDALONEmain(argc, argv)#elseperfmon_main(argc,argv)#endif int argc; char **argv;{ extern struct pixfont *pf_default(); extern char *calloc(); int perf_mon_selected(); int stat; struct inputmask im; int have_disk; fd_set ibits, obits, ebits; if ((stats = (struct statistic *)(LINT_CAST(calloc(MAX_STATS, sizeof(struct statistic))))) == (struct statistic *)0) { (void)fprintf(stderr, "malloc failed (out of swap space?)\n"); exit(1); } nintv = get_namelist("/vmunix", "/dev/kmem"); collect_stats(); etime = 1.0; have_disk = (total_disk_transfers() ? 1 : 0); /* Initialize stats */ FORALLPOSSIBLESTATS(stat) possible_stats[stat] = NO_STAT; num_stats = 0; if (argv++, --argc) { while (argc--) { int option = getcmd(*(argv++), options); if (option >= 0 && option < NUM_POSSIBLE_STATS) { if (num_stats == MAX_STATS) { (void)fprintf(stderr, "MAX_STATS exceed; please recompile!\n"); } else possible_stats[option] = num_stats++; } else (void)fprintf(stderr, "'%s' is not a valid option\n", *(argv-1)); } } if (num_stats == 0) FORALLPOSSIBLESTATS(stat) { if ((stat == DISK_TRANSFERS) && (have_disk == 0)) continue; possible_stats[stat] = num_stats++; if (num_stats == MAX_STATS) break; } init_stat(USER_CPU_PERCENTAGE, 100, "User", " CPU"); init_stat(SYSTEM_CPU_PERCENTAGE, 100, "System", " CPU"); init_stat(IDLE_CPU_PERCENTAGE, 100, "Idle", " CPU"); init_stat(FREE_MEM, 1000, "Free", " memory"); init_stat(DISK_TRANSFERS, 40, "Disk", " transfers"); init_stat(INTERRUPTS, 60, "Interrupts", ""); init_stat(INPUT_PACKETS, (have_disk ? 20 : 40), "Input", " packets"); init_stat(OUTPUT_PACKETS, (have_disk ? 20 : 40), "Output", " packets"); init_stat(COLLISION_PACKETS, 10, "Collision", " packets"); font = pf_default(); FORALLSTATS(stat) { struct pr_size text_size; text_size = pf_textwidth( strlen(stats[stat].label), font, stats[stat].label); graph_x_offset = max(graph_x_offset, text_size.x); text_size = pf_textwidth( strlen(stats[stat].label2), font, stats[stat].label2); graph_x_offset = max(graph_x_offset, text_size.x); } graph_x_offset += 15; (void)gettimeofday(&saved_time, (struct timezone *) NULL); /* Initialize gfxsw ("take over" kind) */ if (gfx = gfxsw_init(0, argv)) { /* * Set up input mask */ (void)input_imnull(&im); im.im_flags |= IM_ASCII; (void)gfxsw_setinputmask(gfx, &im, &im, WIN_NULLLINK, 0, 1); /* * Main loop */ redisplay(); timeleft = timeout; FD_ZERO(&ibits); FD_ZERO(&obits); FD_ZERO(&ebits); (void)gfxsw_select(gfx, perf_mon_selected, ibits, obits, ebits, &timeleft); /* * Cleanup */ (void)gfxsw_done(gfx); exit(0); } else exit(1);}getcmd(to_match, table) /* Modified from ucb/lpr/lpc.c */ register char *to_match; register char **table;{ register char *p, *q; int found, index_local, nmatches, longest; longest = nmatches = 0; found = index_local = -1; for (p = *table; p; p = *(++table)) { index_local++; for (q = to_match; *q == *p++; q++) if (*q == 0) /* exact match? */ return(index_local); if (!*q) { /* the to_match was a prefix */ if (q - to_match > longest) { longest = q - to_match; nmatches = 1; found = index_local; } else if (q - to_match == longest) nmatches++; } } if (nmatches > 1) return(-1); return(found);}init_stat(index_local, maxval, label_1, label_2) int index_local, maxval; char *label_1, *label_2;{ if WANT_STAT(index_local) { index_local = possible_stats[index_local]; stats[index_local].max_val = maxval; stats[index_local].label = label_1; stats[index_local].label2 = label_2; }}#define TIMER_EXPIRED(timer) \ (*timer && ((*timer)->tv_sec == 0) && ((*timer)->tv_usec == 0))perf_mon_selected(gfx_local, ibits, obits, ebits, timer) struct gfxsubwindow *gfx_local; int *ibits, *obits, *ebits; struct timeval **timer;{ if (TIMER_EXPIRED(timer) || (gfx_local->gfx_flags & GFX_RESTART)) { if (gfx_local->gfx_reps) { if (gfx_local->gfx_flags&GFX_DAMAGED) (void)gfxsw_handlesigwinch(gfx_local); if (gfx_local->gfx_flags & GFX_RESTART) { gfx_local->gfx_flags &= ~GFX_RESTART; redisplay(); } else { int *target[CPUSTATES-1], trash; collect_stats(); for (trash = 0; trash < CPUSTATES-1; trash++) target[trash] = &trash; if WANT_STAT(USER_CPU_PERCENTAGE) target[0] = &stats[possible_stats[USER_CPU_PERCENTAGE]].value[num_of_val]; if WANT_STAT(SYSTEM_CPU_PERCENTAGE) target[1] = &stats[possible_stats[SYSTEM_CPU_PERCENTAGE]].value[num_of_val]; if WANT_STAT(IDLE_CPU_PERCENTAGE) target[2] = &stats[possible_stats[IDLE_CPU_PERCENTAGE]].value[num_of_val]; copy_cpu_stats(target); if WANT_STAT(FREE_MEM) stats[possible_stats[FREE_MEM]].value[num_of_val] = pgtok(total.t_free); if WANT_STAT(DISK_TRANSFERS) stats[possible_stats[DISK_TRANSFERS]].value[num_of_val] = total_disk_transfers(); if WANT_STAT(INTERRUPTS) stats[possible_stats[INTERRUPTS]].value[num_of_val] = (rate.v_intr/nintv) - hz; if WANT_STAT(INPUT_PACKETS) stats[possible_stats[INPUT_PACKETS]].value[num_of_val] = packets.input - old_packets.input; if WANT_STAT(OUTPUT_PACKETS) stats[possible_stats[OUTPUT_PACKETS]].value[num_of_val] = packets.output - old_packets.output; if WANT_STAT(COLLISION_PACKETS) stats[possible_stats[COLLISION_PACKETS]].value[num_of_val] = packets.collisions - old_packets.collisions; (void)gettimeofday(¤t_time, (struct timezone *) NULL); if (current_time.tv_sec < saved_time.tv_sec) { /* Super-user must have set the clock back */ saved_time = current_time; saved_time.tv_sec -= SECS_PER_TIME_TICK; } if (saved_time.tv_sec+SECS_PER_TIME_TICK <= current_time.tv_sec) { saved_time = current_time; do_time[num_of_val] = 1; } else do_time[num_of_val] = 0; if (next_display(gfx_local->gfx_pixwin)) gfx_local->gfx_reps--; } } else (void)gfxsw_selectdone(gfx_local); } if (*ibits & (1 << gfx_local->gfx_windowfd)) { struct inputevent event; /* * Read input from window */ if (input_readevent(gfx_local->gfx_windowfd, &event)) { perror("perf_mon"); return; } switch (event_action(&event)) { case 'f': /* faster usec timeout */ if (timeout.tv_usec >= USEC_INC) timeout.tv_usec -= USEC_INC; else { if (timeout.tv_sec >= SEC_INC) { timeout.tv_sec -= SEC_INC; timeout.tv_usec = 1000000-USEC_INC; } } break; case 's': /* slower usec timeout */ if (timeout.tv_usec < 1000000-USEC_INC) timeout.tv_usec += USEC_INC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -