simple kernel state monitor

Rick Hohensee (humbubba@smarty.smart.net)
Thu, 22 Jul 1999 11:28:50 -0400 (EDT)


This little utility, "shakin", weighs in at 4902 bytes dynamically linked
to libc5.4.46 and puts about a 0.1 load average on a 486 with no
optimization. Typical output on a quiescent box looks like this....

ctrl&d to terminate
1987404 1e534c 15479 15590 d event
1987420 1e535c 1450f7 1452ef d jiffies
1989472 1e5b60 3fc2 3fc4 d kstat
1991300 1e6284 11 13 D tv2
1991560 1e6388 f8 f0 D tv1
1992588 1e678c 1450f8 1452f0 D timer_jiffies
1992616 1e67a8 35 31 D count.520
1993020 1e693c 347a 347f d pps_valid
2001200 1e8930 c008a780 c008a980 D dentry_unused
2043564 1f2eac 1a0754 10732 D old.485
2043566 1f2eae 1e001a 1a0001 D oldx.486
2043568 1f2eb0 1e 1a D oldy.487
2043836 1f2fbc 0 a d sel_cons
2043888 1f2ff0 1000000 0 D k_down
2043936 1f3020 8 0 d shift_state
dec.-address-hex. previous current type symbol_name

ctrl&d to terminate

################################################################
/* cLIeNUX shakin
19990717

RIGHTS
Copyright 1999 Rick Hohensee
(Richard Allen Hohensee)
shakin is released for redistribution only as part of an intact entire
cLIeNUX Core, or by itself on the unit of physical distribution medium, or
alone as an electronic message. In particular, shakin is not released for
bundling with any other Linux-based or other operating system
distributions, packages or updates, neither on physically distributed
static storage media nor on publicly accessible repositories.
Modifications to shakin by other authors may be licensed and redistributed
at the pleasure of said authors as patches containing only the
modifications.

USAGE
shakin /path/to/running_kernel's/System.map [ > logfile]

DESCRIPTION
shakin shows a periodic snapshot of recently changed kernel variables
based on a System.map (or subset) and /dev/mem, making the Cheap Quick
Dirty assumption that the world of kernel data symbols consists of nothing
but single ints. shakin is sloppy, but informative. If shakin keeps showing
the same huge wad of info your System.map is probably not the one for the
running kernel.

BUGS
see below

*/

/* ## system header includes */
# include <stdio.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
# include <stdlib.h>
# include <string.h>

/* ## declarations, allocations */
FILE * memmapfile;
char linebuffer[80];

#define ARRAYMAX 2000

int addy[ARRAYMAX], current[ARRAYMAX], previous[ARRAYMAX];
char Type[ARRAYMAX];
char * address, *type, *symbolname ;
int i, line, record, records;
int * swap;
FILE * dev_mem;
char name[ARRAYMAX][48];
long file_position;

/* ## assignments */
char whitespace[] = " \t\n";

/* ### subroutines */

void help()
{ printf("\n\n\nUSAGE: shakin mapfile\n\n"
"mapfile wants to be (a subset of) System.map for the RUNNING kernel.\n "
" 19990718\n");
}

void fuzzysleep() /* randomize the period a bit in hopes of avoiding
"aliasing" anomalies. Gee I LOVE that kinda talk! */
{ sleep(5);
usleep(random() & 0xff);
}

int peek(file_position) /* fseeking grab int from fileoid */
{ long offset ;
offset = fseek( dev_mem, file_position , SEEK_SET );
if ( offset < 0 )
{ printf("The fseek failed. Some devices won't lseek, "
"and fseek is 31 bits,\n 2 gig range.\n");
return -1;
}
else {return( getw(dev_mem ) );
}
}

/* #### main */

void main (int argc,char *argv[]) /* MAIN MAIN MAIN MAIN */
{ if ( argc != 2 )
{ help();
return ;
}

/* open System.map subset and /dev/mem */
memmapfile = fopen(argv[1], "r" ) ;
if ( memmapfile < 0 )
{ help();
printf("failed to open file %s, error %d\n", argv[1], errno);
return;
}

dev_mem = fopen("/dev/mem", "r");
if ( dev_mem < 0 )
{ printf("failure to open special file /dev/mem. mknod?\n");
return;
}

/* fill arrays with names, "previous" values, and addresses for hits */
line = 0;
record = 0;
while ( fgets( linebuffer, 80 , memmapfile) ) /* get line */
{ line ++;
/* Got milk? */
address = strtok(linebuffer , whitespace);
address = ( address + (strlen(address) - 6));
/* cut address to 6 chars with some pointer arithmatic. */

type = strtok(0 , whitespace);
symbolname = strtok(0 , whitespace);

if ( ! strcmp(type, "D") || ! strcmp(type, "d") )
{ record ++;
if (strcmp(type, "D"))
{ Type[record]='D';
}
else { Type[record]='d';
}
addy[record] = strtol(address,0,16);
previous[record] = peek( (long) addy[record]);
printf("%s\n", strcpy(name[record], symbolname) );
/* still two Kurds with one bone using side-effects*/
}
if ( record > ARRAYMAX )
{ printf("the maximum # of records shakin can handle "
"is %d, which has been exceeded.\n Trim your "
"System.map, or change ARRAYMAX in the\n shakin "
" source and recompile.\n", ARRAYMAX );

return;
}

} /* end init while loop */
records = record ;
printf("\n%d records \n", records);
printf("\nctrl&d to terminate\n");
fuzzysleep();

/* on-going "current" loop */
while ( 1 )
{ for (i = 0; i < records ; i ++)
{ current[i] = peek( (long) addy[i]);
if ( current[i] != previous[i] )
printf("%8d %8x %10x %10x %c %s\n",
addy[i], addy[i], previous[i], current[i], Type[i], name[i]);
}
printf(" dec.-address-hex. previous "
" current type symbol_name\n");
memmove(previous, current, records << 2 );
printf("\nctrl&d to terminate\n");
fuzzysleep();
}
}
#########################################################################
Rick Hohensee

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/