?? mosmon.c
字號:
/* Author(s): Amnon Shiloh for Mosix *//* Adapted to OpenMosix from Mosix and bugfixing by David Santo Orcero *//* irbis@orcero.org http://www.orcero.org/irbis *//* Mosix is (c) of prof. Amnon Barak http://www.mosix.org *//* Original code is (c) of prof. Amnon Barak http://www.mosix.org *//* OpenMosix is (c) of Moshe Bar http://www.openmosix.com *//* Each respective trademark is of its own owner *//* All rights reserved. *//* This software is distributed under GPL 2 *//* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTY IS ASSUMED. *//* NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING *//* FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED. IT CAN BURN *//* YOUR HARD DISK, ERASE ALL YOUR DATA AND BROKE DOWN YOUR *//* MICROWAVE OVEN. YOU ARE ADVISED. *//* THIS SOFTWARE IS PROVIDED IN ITS "AS IS" CONDITION, WITH NO WARRANTY *//* WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING *//* FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED. *//*** Last modified on 7 April 2004 by Moreno 'baro' Baricevic** <baro AT democritos DOT it>**** This version of mosmon is independent of kernel headers.** mosmon guesses the size of struct mosix_info (usually correctly!).** The user can specify an arbitrary kernel version using the (new) command line** option "-F <VERSION>". Where version is in the range (2416-2425).**** Other fixes/changes:** - new usage() routine;** - help fixed;** - most of the interactive keys have their command line counterpart;** - log-load display patch (by Tony Travis <ajt@rri.sari.ac.uk>)** has been merged as command line option "-L" and interactive key "L";** - ...*/#include <linux/config.h>#include <stdio.h>#include <stdlib.h>#include <termio.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/time.h>#include <string.h>#include <termios.h>#include <sys/ioctl.h>#include <fcntl.h>#include <errno.h>#include <signal.h>#include <unistd.h>#define PROGNAME "mosmon"#define PROGVER "2.0"#include "utils.h"#include "mosix_info.h"#define USE_LOG_LOAD // enable log-load display (-L option, L key)#ifdef USE_LOG_LOAD# include <math.h>int log_load = 0;#endif /* USE_LOG_LOAD */#include <curses.h>/**************************************************************** map some ncurses keys (<ncurses.h>)*/#define KEY_DOWN 0402 /* Sent by terminal down arrow key */#define KEY_UP 0403 /* Sent by terminal up arrow key */#define KEY_LEFT 0404 /* Sent by terminal left arrow key */#define KEY_RIGHT 0405 /* Sent by terminal right arrow key */#define KEY_HOME 0406 /* Sent by home key. */#define KEY_NPAGE 0522 /* Sent by next-page key */#define KEY_PPAGE 0523 /* Sent by previous-page key */#define KEY_ENTER 0527 /* Enter/send (unreliable) */#define KEY_A1 0534 /* Upper left of keypad */#define KEY_A3 0535 /* Upper right of keypad */#define KEY_B2 0536 /* Center of keypad */#define KEY_C1 0537 /* Lower left of keypad */#define KEY_C3 0540 /* Lower right of keypad */#define KEY_END 0550 /* end key */#define KEY_IC 0513 /* insert-character key *//**************************************************************** first help string (basic help message).** Should fit on 80x24 screen (-2 lines for "\nPress any key...").*/#define HELP_STR1 \"OpenMosix Load Monitor Version " PROGVER ", Based on code (c) by MOSIX GROUP HUJI.\n" \"\n" \"A load unit represents 100% CPU utilisation of a standard processor. If the\n" \"speed of a CPU is the same as the yardstick, one load unit is equivalent\n" \"to a load average of 1.0 as displayed by \"top\", \"mtop\" and \"uptime\".\n" \"However, nodes with faster CPU's and/or SMP nodes with multiple CPU's\n" \"will show a lower load and nodes with slower CPU's will show a higher load.\n" \"\n" \"For larger systems (with 10 or more nodes), node-numbers can be shown either\n"\"horizontally (better looking) or vertically (to see more at a time).\n" \"\n" \"Help for Interactive Keys:\n" \"\n" \"q or Q Quit mosmon\n" \"h or H or ? bring up this help screen\n" \"\n" \"w/v/V/a\t horizontal (wide), vertical, super-vertical (tight) or\n" \" automatic selection of numbering (default auto)\n" \"s display processor-speeds (also number of SMP CPU's)\n" \"m display logically-used vs. total memory\n" \"r display raw-used (non-free) memory vs. total memory\n" \""/**************************************************************** second help string (additional keys)** Should fit on 80x24 screen (-2 lines for "\nPress any key...").*/#define HELP_STR2 \"Additional keys:\n" \"\n" \"l display loads (default, 1.0 = 100% CPU)\n" \"L toggle display of load on log scale (2.0 = 100% CPU)\n" \"d show dead nodes (configured but not-responding)\n" \"t toggle display of total operational node count\n" \" (not recommended on very large clusters - will be very slow)\n" \"y display the yardstick (i.e. speed of a standard processor)\n" \"\n" \"Enter redraw the screen\n" \"Insert force update after OpenMosix is restarted\n" \"\n" \"When not all nodes fit on the screen, press:\n" \"\n" \"Left/Right-Arrow or -/+ \n" \" move one node to the left/right\n" \"p/n move one screen to the left/right (previous/next)\n" \"\n" \"\n" \"Try \"" PROGNAME " -h\" to see command line options or " \"\"man " PROGNAME "\" for details.\n" \"\n"/**************************************************************** functions declaration*/void usage (const char *errmsg, ...);void set_mode (int i);void get_npe (void);void find_npe (void);void adjust_first (void);void ch_alarm (void);void not_yet_ch (int ch);int readc_half_second (void);int my_getch (void);int is_input (void);void help (void);void yardstick (void);void cb (const char *msg, int y, int x);void cb_ctr (const char *msg);void onio (void);void sleep_or_input (unsigned int secs);void onint (int i);/* ! OpenMosix */static voidnot_mosix (void){ fprintf (stderr, PROGNAME ": This is NOT a OpenMosix system!\n"); exit (1);} /* not_mosix *//**************************************************************** some useful macros*/#define COL_FROM_0 7#define MAX_SILENT ( -5 )#define VERY_DEAD ( MAX_SILENT - 1 )#define PROC_HPC_SSPEED "/proc/hpc/admin/sspeed"/**************************************************************** global variables (arrays numbering starts at 1)*/int screen_width;mosix_info_s info[MOSIX_MAX + 1];float load[MOSIX_MAX + 1], other[MOSIX_MAX + 1];char valid[MOSIX_MAX + 1];enum{ D_GETLOAD, D_GETSPEED, D_GETUTIL, D_GETMEM, D_GETBMEM} item = D_GETLOAD;int ifd = -1; /* input file */int npe = 0; /* number of record */int first = 1; /* first node displayed *//**************************************************************** mosix_info_* structures handling stuff*/int (*readstruct) (int, mosix_info_s *, size_t);int vernum = _UNKNOWN;int recsz = 0;char mstruct[16];/************ * MAIN * ************/intmain (int argc, char *argv[]){ int l, col; register int i = 0, j = 0, k = 0; float max, curmax = 0; int cool = 0; int dead; struct winsize ws; int vflg = 0, wflg = 0, tflg = 0; int dflg = 0; int last; int base; /* baseline location */ int ver = 0; int wid; /* width of processor numbers */ char need_count = 1; int tot = 0, tot_display = 0, cpus_display = 0; NCURSES_CONST char *fmt; unsigned int turns = 0; char space, ospace; int rev; int first_read, nread; const char *file = PROC_HPC_INFOS;#ifdef DEBUG stdreopen ();#endif /* ** command line options parser */ while (argc > 1 && (argv[1][0] == '-' || argv[1][0] == '+')) { if (argv[1][0] == '+') { if (!argv[1][1]) usage ("+: NODE_NUMBER missing"); first = strtoi (&argv[1][1]); if (errno == EINVAL) usage ("+: invalid argument \"%s\"", &argv[1][1]); if (errno == ERANGE) usage ("+: argument out of range \"%s\"", &argv[1][1]); if (first < 1 || first > MOSIX_MAX) usage ("+: NODE_NUMBER out of range (1-%d) \"%s\"", MOSIX_MAX, &argv[1][1]); } else { for (j = 1; argv[1][j]; j++) { switch (argv[1][j]) { default: usage ("unrecognized option '%c' in argument \"%s\"", argv[1][j], argv[1]); case 'h': case 'H': usage (NULL); //--------------------------------- case 'v': vflg = 1; wflg = 0; break; case 'V': vflg = 2; wflg = 0; break; case 'w': vflg = 0; wflg = 1; break; case 'a': wflg = vflg = 0; need_count = 1; break; //--------------------------------- case 's': item = D_GETSPEED; break; case 'm': item = D_GETMEM; break; case 'r': item = D_GETBMEM; break; case 'u': item = D_GETUTIL; break;#ifdef USE_LOG_LOAD case 'L': log_load = 1; // fall through#endif /* USE_LOG_LOAD */ case 'l': item = D_GETLOAD; break; //--------------------------------- case 't': tflg = 1; break; case 'd': dflg = 1; break; //--------------------------------- case 'F': if (!argv[2] || !*argv[2]) usage ("-%c: missing argument", argv[1][j]); { int struct_ver = strtoi (argv[2]); if (errno == EINVAL) usage ("-%c: invalid argument \"%s\"", argv[1][j], argv[2]); if (errno == ERANGE) usage ("-%c: argument out of range \"%s\"", argv[1][j], argv[2]); vernum = force_version (struct_ver); if (vernum == _UNKNOWN) // your fault, not mine usage ("-%c: unknown version \"%s\"", argv[1][j], argv[2]); fprintf (stderr, "force using struct %s\n", mstruct); argc--; argv++; goto skip_arg; } } } } skip_arg: argc--; argv++; } if (argc > 1) usage ("too many arguments [%s]", argv[1]); DBGprint ("using file \"%s\" ...", file); ifd = open (file, O_RDONLY); if (ifd == -1) not_mosix ();#ifdef DEBUG summary ();#endif /* DEBUG */ if (vernum == _UNKNOWN) vernum = guess_by_recsz (ifd); DBGprint ("vernum = %d", vernum); DBGprint ("recsz = %d", recsz);/*// if ( vernum == _UNKNOWN )// die( "*** unsupported record" );** No. Continue, OpenMosix can be configured later** (DUMMY struct saves us from segfault)*/ get_npe (); // get the number of records from PROC_HPC_INFOS /* ** ok, start ncurses ** trap some signals in order to clear the screen before exit. */ signal (SIGINT, (sig_t) onint); signal (SIGQUIT, (sig_t) onint); initscr (); noecho (); cbreak (); system ("stty cbreak -echo"); for (i = 0; i <= npe; i++) load[i] = 0; while (1) // start neverending loop { // if oM un/configured while we are running, recheck for recsz and npe. if (vernum == _UNKNOWN) vernum = guess_by_recsz (ifd), get_npe (); first_read = nread = 0; /* get the new (if changed) win size */ if (ioctl (STDIN_FILENO, TIOCGWINSZ, (char *) &ws) == -1) fprintf (stderr, "ioctl() failed: [%d] %m\n", errno), onint (1); if ((COLS != ws.ws_col) || (LINES != ws.ws_row)) { initscr (); need_count = 1; } if (tflg) { memset (&info[1], 0, npe * RECSZ_STD); // clear records buffer (void) lseek (ifd, 0L, SEEK_SET); // goto start of file j = readstruct (ifd, &info[1], npe); // read the whole file content DBGprint ("j = %d", j); if (j < npe) { npe = j; adjust_first (); } first_read = 1; nread = npe; /* ** check for invalid records (dead nodes) */ for (tot_display = 0, cpus_display = 0, i = 1; i <= npe; i++) { if (info[i].status & DS_MOSIX_UP) { tot_display++; cpus_display += info[i].ncpus; valid[i] = 1; load[i] = -1; } else if ((info[i].status & DS_MOSIX_DEF) && valid[i] > (turns >= -MAX_SILENT ? MAX_SILENT : -(int64_t) turns)) { tot_display++; cpus_display += info[i].ncpus; } } } if (need_count && !vflg && !wflg) { get_npe (); k = (COLS - COL_FROM_0 - 1) + 1; tot = 0; /* we only need to answer whether there are at least k * nodes up ahead or not: once we have the answer, * stop reading. Of course, with "tflg" we have already * read everything */ first_read = first; if (!tflg) nread = 0; for (i = first; i <= npe && tot < k; i += k) { last = i + k - 1; if (last > npe) last = npe; if (!tflg) { (void) lseek (ifd, i - 1, SEEK_SET); j = readstruct (ifd, &info[i], (last - i + 1)); if (j < (last - i + 1)) last = npe = i + j - 1; nread = last + 1 - first; } for (j = i; j <= last && tot < k; j++) if (info[j].status & (dflg ? DS_MOSIX_DEF : DS_MOSIX_UP)) tot++; } need_count = 0; } /* calculate the screen_width */ wid = 1 + (npe > 9) + (npe > 99) + (npe > 999) + (npe > 9999); k = (COLS - COL_FROM_0 - 1) / (wid + 1); if (vflg) { vert: base = LINES - 2 - wid; ver = 1; if (vflg == 2) { wid = 0; screen_width = (COLS - COL_FROM_0 - 1); } else { wid = 1; screen_width = (COLS - COL_FROM_0 - 1) / 2; } adjust_first (); } else if (wflg || k >= tot || (COLS - COL_FROM_0 - 1) < tot) { ver = 0; screen_width = k; base = LINES - 3; } else goto vert; move (0, 0); clrtobot (); if (item == D_GETMEM || item == D_GETBMEM) { if (item == D_GETBMEM) { fmt = "Raw Used Memory"; i = base / 2 - 8; if (i < 1) i = 1; } else { fmt = "Used Memory"; i = base / 2 - 6; j = 1; } for (; *fmt; i++) { move (i, 0); addch ((chtype) * fmt++); } while (i == base / 4 || i == base / 2 || i == base * 3 / 4) i++; if (i < base) { move (i, 2); addstr ("(MB)"); } } else if (item == D_GETLOAD) {#ifdef USE_LOG_LOAD int n = (log_load) ? 7 : 3; fmt = (log_load) ? "LOG LOAD" : "LOAD";#else int n = 3; fmt = "LOAD";#endif /* USE_LOG_LOAD */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -