📄 perfmon.c
字号:
#ifndef lintstatic char sccsid[] = "@(#)perfmon.c 1.1 92/07/30 Copyright Sun Micro";#endif/* * Copyright (c) 1987 by Sun Microsystems, Inc. *//* * This code was lifted from standard UNIX "perfmon" utility, and then modified * to run on a canvas subwindow in Sundiag. *//* * 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 <signal.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 <rpc/rpc.h>#include <utmp.h>#include <rpcsvc/rstat.h>#include <netdb.h>#include "sundiag.h" /* -JCH- will also include SunView files */extern time_t time();struct 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;static struct timezone dummy_zone;static struct timeval TIMEOUT = {60, 0};/* * 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 PACKETS 2#define PAGING 3#define INTERRUPTS 4#define DISK_TRANSFERS 5#define CONTEXT_SW 6#define LOAD_AVE 7#define COLLISION_PACKETS 8#define ERROR_PACKETS 9#define NUM_POSSIBLE_STATS 10static int possible_stats[NUM_POSSIBLE_STATS];#define WANT_STAT(x) (possible_stats[(x)] != NO_STAT)#define MAX_STATS 11static struct statistic *p_stats;static struct{ int gfx_flags; int gfx_reps; struct pixwin *gfx_pixwin; struct rect gfx_rect;} mygfx, *gfx = &mygfx; /* -JCH- */static int first=1; /* -JCH- the first time to display */static int num_stats, num_of_val = 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 \/ *************** *//* forward declaration */static void redisplay();extern xdr_statsswtch();char *sprintf(), *strcpy();long lseek();int firstfree, maxfree;int hz;int sick;int getdata_swtch(); /* version 3 (RSTATVERS_SWTCH) of RSTATPROG */int getdata_var(); /* version 4 (RSTATVERS_VAR) */struct vmmeter osum;int deficit;double etime;int mf;long t;static int ans[MAX_STATS]; int debug = 0;#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 ^ **************** */static int oldsocket = -1;#define VER_NONE -1static int vers = VER_NONE ;static int cpustates ;static int dk_ndrive ;perfmon_main(){ extern char *calloc(); int stat; int have_disk; if ((p_stats = (struct statistic *)(LINT_CAST(calloc(MAX_STATS, sizeof(struct statistic))))) == (struct statistic *)0) { (void)fprintf(stderr, "malloc failed (out of swap space?)\n"); sundiag_exit(1); } (void)setup(); if (vers == RSTATVERS_VAR) (void)getdata_var(); else (void)getdata_swtch(); etime = 1.0; have_disk = (ans[DISK_TRANSFERS] ? 1 : 0); /* Initialize stats */ FORALLPOSSIBLESTATS(stat) possible_stats[stat] = NO_STAT; num_stats = 0; 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(PACKETS, (have_disk ? 40 : 60), "Total", " packets"); init_stat(PAGING, 20, "", "Paging"); init_stat(INTERRUPTS, 400, "Inter-", " rupts"); init_stat(DISK_TRANSFERS, 40, "Disk", " transfers "); init_stat(CONTEXT_SW, 128, "Context", " Switches"); init_stat(LOAD_AVE, 10, "Load", " Average"); init_stat(COLLISION_PACKETS, (have_disk ? 4 : 8), "Collision", " packets"); init_stat(ERROR_PACKETS, (have_disk ? 10 : 20), "Error", " packets"); font = sundiag_font; /* always use the Sundiag font -JCH- */ FORALLSTATS(stat) { struct pr_size text_size; text_size = pf_textwidth( strlen(p_stats[stat].label), font, p_stats[stat].label); graph_x_offset = max(graph_x_offset, text_size.x); text_size = pf_textwidth( strlen(p_stats[stat].label2), font, p_stats[stat].label2); graph_x_offset = max(graph_x_offset, text_size.x); } graph_x_offset += 15; (void)gettimeofday(&saved_time, &dummy_zone);/* -JCH- modified so that it will run on a canvas subwindow. */ gfx->gfx_pixwin = canvas_pixwin(sundiag_perfmon); (void)window_set(sundiag_perfmon, CANVAS_RESIZE_PROC, redisplay, 0);/* -JCH- */}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]; p_stats[index_local].max_val = maxval; p_stats[index_local].label = label_1; p_stats[index_local].label2 = label_2; }}#define YORIGIN_FOR_STAT(num) \ (((num)*rect.r_height)/num_stats)#define YMIDPOINT_FOR_STAT(num) \ (((num)*rect.r_height+rect.r_height/2)/num_stats - 6) /* -JCH- */static int Y_FOR_STAT_VAL(stat, num_of_val, height_of_stat)int stat, num_of_val, height_of_stat;{ int temp; (void)signal(SIGFPE, SIG_IGN); temp = YORIGIN_FOR_STAT(stat)+5+height_of_stat - min(height_of_stat, (height_of_stat*(p_stats[stat].value[num_of_val]-p_stats[stat].min_val)/ (p_stats[stat].max_val-p_stats[stat].min_val))); (void)signal(SIGFPE, SIG_DFL); return(temp);}display_dividers(pw, clear_first) struct pixwin *pw; int clear_first;{ register int i, stat; struct rect div_rect; div_rect.r_left = graph_x_offset; div_rect.r_width = rect.r_width-graph_x_offset; div_rect.r_height = 5; FORALLSTATS(stat) { register int y_origin_of_stat = YORIGIN_FOR_STAT(stat); if (stat == 0) continue; div_rect.r_top = y_origin_of_stat-2; (void)pw_lock(pw, &div_rect); if (clear_first) (void)pw_writebackground(pw, div_rect.r_left, div_rect.r_top, div_rect.r_width, div_rect.r_height, PIX_CLR); /* Draw the horizontal line and then add the tick marks */ (void)pw_vector(pw, div_rect.r_left, y_origin_of_stat, rect.r_width, y_origin_of_stat, PIX_SRC, -1); for (i = 0; i < num_of_val; i++) { if (do_time[i]) (void)pw_vector(pw, graph_x_offset+i, div_rect.r_top, graph_x_offset+i, y_origin_of_stat+2, PIX_SRC, -1); } (void)pw_unlock(pw); }}static void redisplay(){ register int height_of_stat, stat; rect = *(struct rect *)window_get(sundiag_perfmon, WIN_RECT); (void)pw_writebackground(gfx->gfx_pixwin, 0, 0, rect.r_width, rect.r_height, PIX_CLR); display_dividers(gfx->gfx_pixwin, 0); height_of_stat = YORIGIN_FOR_STAT(1) - YORIGIN_FOR_STAT(0) - 10; FORALLSTATS(stat) { register int font_height = (font->pf_defaultsize.y)+2; register int y_origin_of_stat = YORIGIN_FOR_STAT(stat); struct pr_size text_size; char temp[10]; (void)pw_text(gfx->gfx_pixwin, 0, YMIDPOINT_FOR_STAT(stat), PIX_SRC, font, p_stats[stat].label); (void)pw_text(gfx->gfx_pixwin, 0, YMIDPOINT_FOR_STAT(stat)+font_height, PIX_SRC, font, p_stats[stat].label2); (void)sprintf(temp, "%d", p_stats[stat].max_val); text_size = pf_textwidth(strlen(temp), font, temp); (void)pw_text(gfx->gfx_pixwin, graph_x_offset-5-text_size.x, y_origin_of_stat-3+font_height, PIX_SRC, font, temp); (void)sprintf(temp, "%d", p_stats[stat].min_val); text_size = pf_textwidth(strlen(temp), font, temp); (void)pw_text(gfx->gfx_pixwin, graph_x_offset-5-text_size.x, y_origin_of_stat+8+height_of_stat, PIX_SRC, font, temp); } if (num_of_val > 0) FORALLSTATS(stat) { redisplay_stat_values( gfx->gfx_pixwin, height_of_stat, stat, 0, num_of_val); }}redisplay_stat_values(pw, height_of_stat, stat, start, stop_plus_one) struct pixwin *pw; int height_of_stat, stat, start, stop_plus_one;{ int j, newY; (void)pw_lock(pw, &rect); newY = Y_FOR_STAT_VAL(stat, start, height_of_stat); for (j = start; j < stop_plus_one; ) { int jcopy = j, oldY = newY; do { newY = Y_FOR_STAT_VAL(stat, j, height_of_stat); j++; } while ((oldY == newY) && (j < stop_plus_one)); if (j > jcopy+1) (void)pw_vector(pw, graph_x_offset+jcopy, oldY, graph_x_offset+j-2, oldY, PIX_SRC, 1); (void)pw_vector(pw, graph_x_offset+j-2, oldY, graph_x_offset+j-1, newY, PIX_SRC, 1); } (void)pw_unlock(pw);}set_clipping_equal_fixup(pw) struct pixwin *pw;{ int screenX, screenY; struct rect screenrect; screenrect = rect; (void)win_getscreenposition( pw->pw_clipdata->pwcd_windowfd, &screenX, &screenY); screenrect.r_left = screenX; screenrect.r_top = screenY; (void)rl_free(&pw->pw_clipdata->pwcd_clipping); pw->pw_clipdata->pwcd_clipping = pw->pw_fixup; pw->pw_fixup = rl_null; (void)_pw_setclippers(pw, &screenrect);}next_display(pw) struct pixwin *pw;{ int stat, height_of_stat; height_of_stat = YORIGIN_FOR_STAT(1) - YORIGIN_FOR_STAT(0) - 10; FORALLSTATS(stat) { int newY, oldY; newY = Y_FOR_STAT_VAL(stat, num_of_val, height_of_stat); if (num_of_val == 0) oldY = newY; else oldY = Y_FOR_STAT_VAL(stat, num_of_val-1, height_of_stat); (void)pw_vector(pw, graph_x_offset+num_of_val, oldY, graph_x_offset+num_of_val+1, newY, PIX_SRC, 1); if ((stat != 0) && do_time[num_of_val]) { int y_origin_of_stat = YORIGIN_FOR_STAT(stat); (void)pw_vector(pw, graph_x_offset+num_of_val, y_origin_of_stat-2, graph_x_offset+num_of_val, y_origin_of_stat+2, PIX_SRC, -1); } } if (++num_of_val >= NUM_VALS_PER || num_of_val >= rect.r_width-graph_x_offset) { if (shift_left_on_new_cycle) { int num_shift_left = (rect.r_width-graph_x_offset)/2; int width = (rect.r_width-graph_x_offset) - num_shift_left; register int j; if (num_shift_left < 0) num_shift_left = num_of_val-1; /* -JCH- fixed the bug which causes core dump when the window was resized to reveal only the label portion */ for (j = num_shift_left; j < num_of_val; j++) do_time[j-num_shift_left] = do_time[j]; FORALLSTATS(stat) { int ys = YORIGIN_FOR_STAT(stat)+5; for (j = num_shift_left; j < num_of_val; j++) p_stats[stat].value[j-num_shift_left] = p_stats[stat].value[j]; (void)pw_copy(pw, graph_x_offset, ys, width, height_of_stat+1, PIX_SRC, pw, graph_x_offset+num_shift_left, ys); if (!rl_empty(&pw->pw_fixup)) { set_clipping_equal_fixup(pw); (void)pw_writebackground( pw, 0, 0, rect.r_width, rect.r_height, PIX_SRC); redisplay_stat_values( pw, height_of_stat, stat, 0, num_of_val-num_shift_left-1); (void)pw_exposed(pw); } (void)pw_writebackground( pw, graph_x_offset+num_shift_left, ys, width, height_of_stat+1, PIX_SRC); } num_of_val -= num_shift_left+1; display_dividers(pw, 1); } else { num_of_val = 0; } }}#define TIMER_EXPIRED(timer) \ (*timer && ((*timer)->tv_sec == 0) && ((*timer)->tv_usec == 0))perfmon_update(){ int *target[CPUSTATES-1], trash; if (first == 1) /* -JCH- */ { redisplay(); /* display the graphics for the first time */ first = 0; /* reset the flag */ } /* get stats from rstatd - fill in ans[]. */ if (vers == RSTATVERS_VAR) (void)getdata_var(); else (void)getdata_swtch(); if WANT_STAT(USER_CPU_PERCENTAGE) p_stats[possible_stats[USER_CPU_PERCENTAGE]].value[num_of_val] = ans[USER_CPU_PERCENTAGE]; if WANT_STAT(SYSTEM_CPU_PERCENTAGE) p_stats[possible_stats[SYSTEM_CPU_PERCENTAGE]].value[num_of_val] = ans[SYSTEM_CPU_PERCENTAGE]; if WANT_STAT(DISK_TRANSFERS) p_stats[possible_stats[DISK_TRANSFERS]].value[num_of_val] = ans[DISK_TRANSFERS]; if WANT_STAT(INTERRUPTS) p_stats[possible_stats[INTERRUPTS]].value[num_of_val] = ans[INTERRUPTS]; if WANT_STAT(PACKETS) p_stats[possible_stats[PACKETS]].value[num_of_val] = ans[PACKETS]; if WANT_STAT(ERROR_PACKETS) p_stats[possible_stats[ERROR_PACKETS]].value[num_of_val] = ans[ERROR_PACKETS] / FSCALE; if WANT_STAT(COLLISION_PACKETS) p_stats[possible_stats[COLLISION_PACKETS]].value[num_of_val] = ans[COLLISION_PACKETS] / FSCALE; if WANT_STAT(LOAD_AVE) p_stats[possible_stats[LOAD_AVE]].value[num_of_val] = ans[LOAD_AVE] / FSCALE; if WANT_STAT(PAGING)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -