[comp.unix.aux] How do I read the load average values from /dev/kmem?

orachat@seashell.seas.ucla.edu (Orachat Choedamphai) (03/23/90)

Hello,

I'm trying to get the value of the variable "avenrun" from /dev/kmem. The
following is a program that I used.  Could someone please tell me what I did
wrong or maybe someone could send me a C program that will do this job? 
I would appreciate any help or suggestion.  Thank you in advance.

_Orachat
 
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/file.h>
#include <a.out.h> 

#define  UNIX 	"/unix"

int 	kmemf;  /* descriptor of /dev/kmem */	

struct nlist nl[2];

extern int errno;

main ()
{
	float avenrun[3];

	(void) strcpy (nl[0].n_name, "avenrun");
	(void) strcpy (nl[1].n_name, "0");
        nlist(UNIX, nl);
	if (nl[0].n_value == 0) {
                fprintf (stderr, "/vmunix: No namelist\n");  
		exit(1);
        }
	 printf ("address = %d\n", nl[0].n_value);
        if ((kmemf = open("/dev/kmem", O_RDONLY)) < 0) {
                perror ("/dev/kmem");
                exit (1);
        }
        if (lseek (kmemf, (off_t)nl[0].n_value, 0) < 0)
		printf ("lseek failed\n");;
        (void) read (kmemf, (char *)avenrun, sizeof(avenrun));
	 printf ("load = %e,%e,%e\n", avenrun[0], avenrun[1], avenrun[2]); 
}

rmtodd@servalan.uucp (Richard Todd) (03/23/90)

orachat@seashell.seas.ucla.edu (Orachat Choedamphai) writes:

>Hello,

>I'm trying to get the value of the variable "avenrun" from /dev/kmem. The
>following is a program that I used.  Could someone please tell me what I did
>wrong or maybe someone could send me a C program that will do this job? 
>I would appreciate any help or suggestion.  Thank you in advance.
Well, I can see two problems with the code:

>...
>	float avenrun[3];
The avenrun array is actually an array of longs, scaled by 65536.  
So this should be
	long avenrun[3];
>	(void) strcpy (nl[0].n_name, "avenrun");
>	(void) strcpy (nl[1].n_name, "0");
  The nlist routines require the name in the last entry to be the empty
string "".  Putting in "0" instead may be confusing it.

>        (void) read (kmemf, (char *)avenrun, sizeof(avenrun));
>	 printf ("load = %e,%e,%e\n", avenrun[0], avenrun[1], avenrun[2]); 
>}
  Since the values are scaled longs, this should be:
        printf("load = %e %e %e", avenrun[0]/65536.0, avenrun[1]/65536.0,
               avenrun[2]/65536.0);

Alas, this sort of thing (the format of kernel variables) isn't really well
documented, and it varies greatly among systems.  As I recall, PDP-11s running
BSD2.10 store the avenrun values as ints scaled by 256, Suns store them as 
floats, and getting the load average on an Encore Multimax is *really* messy.
The lack of documentation for kernel internal variables is one of my really
big pet peeves; basically the way you find out how avenrun[] is stored on
a system (assuming you don't have kernel source) is to try interpreting the
values you read in various formats until you find one that doesn't give
gibberish.  Bletch.  
--
Richard Todd	rmtodd@uokmax.ecn.uoknor.edu  rmtodd@chinet.chi.il.us
	rmtodd@servalan.uucp
Motorola Skates On Intel's Head!