//------------------------------------------------------------------- // activity.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. // // compile-and-link using: $ g++ activity.cpp -o activity // // This program makes use of the 'select()' library-function to // support efficient handling of its multiplexed program-input. // It requires that an accompanying kernel object (activity.ko) // has already been compiled and installed in the Linux kernel. // // NOTE: Developed and tested with Linux kernel version 2.6.12. // // programmer: ALLAN CRUSE // written on: 08 MAY 2006 //------------------------------------------------------------------- #include // for printf(), fprintf() #include // for open() #include // for exit() #include // for read(), write(), close() #include // for tcgetattr(), tcsetattr() #define KEY_ESCAPE 27 // ASCII code for ESCAPE-key #define FILENAME "/proc/activity" // name of input pseudo-file int main( void ) { // open the pseudo-file for reading int fd = open( FILENAME, O_RDONLY ); if ( fd < 0 ) { fprintf( stderr, "could not find \'%s\' \n", FILENAME ); exit(1); } // enable noncanonical terminal-mode struct termios tty_orig; tcgetattr( STDIN_FILENO, &tty_orig ); struct termios tty_work = tty_orig; tty_work.c_lflag &= ~( ECHO | ICANON | ISIG ); tty_work.c_cc[ VMIN ] = 1; tty_work.c_cc[ VTIME ] = 0; tcsetattr( STDIN_FILENO, TCSAFLUSH, &tty_work ); // initialize file-descriptor bitmap for 'select()' fd_set permset; FD_ZERO( &permset ); FD_SET( STDIN_FILENO, &permset ); FD_SET( fd, &permset ); // initialize the screen-display printf( "\e[H\e[J" ); // clear the screen printf( "\e[?25l" ); // hide the cursor // draw the screen's title, headline and sideline int i, ndev = 1+fd, row = 2, col = 27; printf( "\e[%d;%dHINTERRUPT ACTIVITY MONITOR", row, col ); for (i = 0; i < 16; i++) { row = i+6; col = 6; printf( "\e[%d;%dH%02X:", row, col, i*16 ); row = 5; col = i*4 + 12; printf( "\e[%d;%dH%X", row, col, i ); } fflush( stdout ); // main loop: continuously responds to multiplexed input for(;;) { // sleep until some new data is ready to be read fd_set readset = permset; if ( select( ndev, &readset, NULL, NULL, NULL ) < 0 ) break; // process new data read from the keyboard char inch; if ( FD_ISSET( STDIN_FILENO, &readset ) ) if ( read( STDIN_FILENO, &inch, 1 ) > 0 ) if ( inch == KEY_ESCAPE ) break; // process new data read from the pseudo-file if ( FD_ISSET( fd, &readset ) ) { unsigned long counter[ 256 ] = {0}; lseek( fd, 0, SEEK_SET ); if ( read( fd, counter, 1024 ) < 1024 ) break; for (i = 0; i < 256; i++) { int row = ( i / 16 ) + 6; int col = ( i % 16 ) * 4 + 10; unsigned long what = counter[ i ] % 1000; printf( "\e[%d;%dH", row, col ); if ( !counter[i] ) printf( "---" ); else printf( "%03d", what ); } row = 23; col = 0; } fflush( stdout ); } // restore the standard user-interface tcsetattr( STDIN_FILENO, TCSAFLUSH, &tty_orig ); printf( "\e[23;0H\e[?25h\n" ); // show the cursor }