//------------------------------------------------------------------- // intwatch.cpp // // This application continuously reads the volatile kernel data // that is stored in a pseudo-file (named '/proc/activity') and // displays it on the screen until the key is pressed. // The 'data' consists of an array of 256 counters representing // invocations of the kernel's 256 interrupt service routines. // // NOTE: The counters may be reset by pressing the key. // // Before running this program you must compile and install our // accompanying 'activity.c' kernel module. // // programmer: ALLAN CRUSE // written on: 23 MAR 2005 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read(), write(), close() #include // for tcgetattr(), tcsetattr() int main( int argc, char **argv ) { // open the pseudo-file for read and write access char filename[] = "/proc/activity"; int fd = open( filename, O_RDWR ); if ( fd < 0 ) { perror( filename ); exit(1); } // preserve the current terminal settings struct termios save_tty; tcgetattr( STDIN_FILENO, &save_tty ); // setup the terminal for noncanonical mode struct termios work_tty = save_tty; work_tty.c_lflag &= ~( ICANON | ECHO ); work_tty.c_cc[ VMIN ] = 1; work_tty.c_cc[ VTIME ] = 0; tcsetattr( STDIN_FILENO, TCSANOW, &work_tty ); // erase the display, hide the cursor. and draw title printf( "\e[H\e[J" ); // clear the screen printf( "\e[?25l\e[?1c" ); // cursor invisible printf( "\e[%d;%dH INTERRUPT ACTIVITY MONITOR ", 3, 27 ); for (int i = 0; i < 16; i++) { int row, col; col = 7, row = i+7; printf( "\e[%d;%dH%02X:", row, col, i*16 ); row = 6, col = i*4 + 13; printf( "\e[%d;%dH%X", row, col, i ); } // main program loop uses 'select' for multiplexed input int done = 0; while ( !done ) { // use 'select()' to sleep until new input is available fd_set readset; FD_ZERO( &readset ); FD_SET( STDIN_FILENO, &readset ); FD_SET( fd, &readset ); if ( select( 1+fd, &readset, NULL, NULL, NULL ) < 0 ) break; // process new input from keyboard if ( FD_ISSET( STDIN_FILENO, &readset ) ) { int inch = 0; if ( read( STDIN_FILENO, &inch, 4 ) > 0 ) { lseek( fd, 0LL, SEEK_SET ); if ( inch == 0x1B ) done = 1; else if ( inch == 0x20 ) write( fd, &inch, 1 ); } } // process new input from pseudo-file if ( FD_ISSET( fd, &readset ) ) { unsigned long counter[ 256 ] = {0}; lseek( fd, 0LL, SEEK_SET ); if ( read( fd, counter, 1024 ) < 1024 ) break; for (int i = 0; i < 256; i++) { int row = ( i / 16 ) + 7; int col = ( i % 16 ) * 4 + 11; int what = counter[ i ] % 1000; if ( !counter[ i ] ) printf( "\e[%d;%dH---", row, col ); else printf( "\e[%d;%dH%03d", row, col, what ); } printf( "\e[%d;%dH", 24, 0 ); } fflush( stdout ); } printf( "\e[?25h\e[?0c" ); // restore visible cursor printf( "\e[%d;%dH", 24, 0 ); // place cursor at bottom tcsetattr( STDIN_FILENO, TCSAFLUSH, &save_tty ); close( fd ); // close the pseudo-file }