home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2135 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  7.3 KB

  1. From: tchrist@convex.com (Tom Christiansen)
  2. Newsgroups: comp.lang.perl,alt.sources
  3. Subject: kernel monitoring, or interactively talking to a pipe
  4. Message-ID: <109131@convex.convex.com>
  5. Date: 21 Nov 90 22:51:00 GMT
  6.  
  7. Here is a program that sits around a looks at kernel memory location to
  8. record certain values.  It's like vmstat, but more generalized. It does
  9. so by opening a pipe (ok, 2 of them) to adb and sending a it command,
  10. then reading a line back, etc.
  11.  
  12. For example:
  13.  
  14.     % vmscan 
  15.     usage: ./vmscan [-sleep] symbol ...
  16.     Valid symbols are: "Context Sw (p)", "Context Sw (v)", "Disk Wait", "Free",
  17.                "Idle", "Idle 1", "Idle 2", "Idle 3", "Interrupts",
  18.                "Page Ins", "Page Outs", "Page Wait", "Pgin", "Pgout",
  19.                "Real", "Reclaims", "Runnable", "Sleeping", "Swapped",
  20.                "Sys.", "System", "System 1", "System 2", "System 3",
  21.                "System calls", "User", "User (n)", "User (n) 1", "User
  22.                (n) 2", "User (n) 3", "User 1", "User 2", "User 3",
  23.                "Virt.", "ccu0", "ccu1", "ccu2", "ccu3", "ccu4", "ccu5",
  24.                "ccu6", "ccu7"
  25.  
  26.     % vmscan -2 User System "User (n)"
  27.     User            System          User (n)
  28.     637             61316           46089
  29.     637             61320           46108
  30.     637             61336           46132
  31.     637             61341           46166
  32.     637             61346           46192
  33.     ...
  34.  
  35.  
  36. Things that you'll have to change to make it work on 
  37. your system:
  38.  
  39. 1) There is a table with commands like this:
  40.  
  41.     User                    cp_time+0/wt
  42.     User (n)                cp_time+4/wt
  43.     System                  cp_time+8/wt
  44.  
  45.     The precise syntax of the adb command (Convex's is bizarre), 
  46.     and especially the mapping between symbols you recognize
  47.     and the ones your kernel does will need changing.
  48.  
  49. 2)  The number of initial garbage lines adb puts out when 
  50.     talking on a pipe may vary.  It may be none.  You will
  51.     find this in the code.
  52.  
  53. 4)  I've hard-wired $TIOCGWINSZ instead of getting it from ioctl.p[lh]
  54.     as a Careful Programmer should.
  55.  
  56. 3)  You should really be running perl. :-)
  57.  
  58. 4)  You may have to install this setgid kmem to read /dev/mem.
  59.  
  60.  
  61. For true perl aficcionados:
  62.  
  63. 1)  You will notice that I use a dynamic format based on window size.
  64.     This is done by using an ioctl to get the window size.    That
  65.     way the usage message is really cool and uses however many 
  66.     columns your window has.
  67.  
  68. 2)  There is a subroutine called &open2 which is like a regular
  69.     open but you get both a read and a write handle.  This is ok
  70.     in this case cause I know that adb reads a line at a time,
  71.     then writes a line at a time.  You should be able to extract
  72.     this and use as is in other programs.  In fact, this is the
  73.     main reason I'm posting this.  If you don't have a recent
  74.     perl patch, quote your filehandle arguments when passing them.
  75.  
  76. --tom
  77.  
  78.  
  79. #!/usr/bin/perl
  80. # vmscan: read stuff out of the kernel like vmstat
  81. # tom christiansen <tchrist@convex.com>
  82.  
  83.  
  84. # look for any -sleep switch
  85. #
  86. if ($ARGV[0] =~ /^-(\d+)/) {
  87.     $snooze = $1;
  88.     shift;
  89. } else {
  90.     $snooze = 30; 
  91. }
  92.  
  93. # set path so taintperl doesn't hate us if running suid
  94. $ENV{'PATH'} = '/bin:/usr/bin:/usr/ucb:/usr/convex:/usr/local';
  95.  
  96. die "$0: can't read /dev/mem\n" unless -r '/dev/mem';
  97. die "$0: can't read /vmunix\n"  unless -r '/vmunix';
  98.  
  99. # now be very careful to keep at least one
  100. # tab between the LHS and the RHS, and that
  101. # LHS have no trailing spaces.
  102.  
  103. %code = split(/[\t\n]+/, <<EO_LIST);
  104. User            cp_time+0/wt
  105. User (n)        cp_time+4/wt
  106. System            cp_time+8/wt
  107. Idle            cp_time+0xc/wt
  108. User 1            cp_time+10/wt
  109. User (n) 1        cp_time+14/wt
  110. System 1        cp_time+18/wt
  111. Idle 1            cp_time+0x1c/wt
  112. User 2            cp_time+20/wt
  113. User (n) 2        cp_time+24/wt
  114. System 2        cp_time+28/wt
  115. Idle 2            cp_time+0x2c/wt
  116. User 3            cp_time+30/wt
  117. User (n) 3        cp_time+34/wt
  118. System 3        cp_time+38/wt
  119. Idle 3            cp_time+0x3c/wt
  120. Runnable        total+0/h
  121. Disk Wait        total+2/h
  122. Page Wait        total+4/h
  123. Swapped            total+8/h
  124. Sleeping        total+6/h
  125. Virt.            total+0xe/wt
  126. Real            total+0x10/wt
  127. Free            total+0x14/wt
  128. Reclaims        cnt+0x38/wt
  129. Page Ins        cnt+0x30/wt
  130. Page Outs        cnt+0x34/wt
  131. Pgin            cnt+0x38/wt
  132. Pgout            cnt+0x3c/wt
  133. Interrupts        cnt+0x10/wt
  134. System calls        cnt+0xc/wt
  135. Context Sw (p)        cnt+0/wt
  136. Context Sw (v)        cnt+0x4/wt
  137. Sys.            cnt+0xc/wt
  138. ccu0            500/wt
  139. ccu0            5b0/wt
  140. ccu1            504/wt
  141. ccu1            5b4/wt
  142. ccu2            508/wt
  143. ccu2            5b8/wt
  144. ccu3            50c/wt
  145. ccu3            5bc/wt
  146. ccu4            510/wt
  147. ccu4            5c0/wt
  148. ccu5            514/wt
  149. ccu5            5c4/wt
  150. ccu6            518/wt
  151. ccu6            5c8/wt
  152. ccu7            51c/wt
  153. ccu7            5cc/wt
  154. EO_LIST
  155.  
  156. &usage if @ARGV <= 0;
  157.  
  158. for (@ARGV) { 
  159.     next if defined $code{$_};
  160.     warn "$0: \"$_\" is an undefined entry point\n";
  161.     &usage;
  162. }
  163.  
  164.  
  165. # also helps for when we fork to keep the 
  166. # stdout buffer empty in the kid
  167. #
  168. select(STDOUT);  $| = 1; # unbuffer
  169.  
  170. # print out symbol headers
  171. for (@ARGV) {
  172.     print $_, "\t";
  173.     print "\t" if 8 > length;
  174. }
  175. print "\n";
  176.  
  177.  
  178. # in case the worst happens
  179. sub REAPER {
  180.     wait;
  181.     print STDERR "$0: kid died unexpectedly: status $?\n";
  182.     exit 2;
  183. $SIG{'PIPE'} = $SIG{'CHLD'} = 'REAPER';
  184.  
  185. &open2(DAD_RDR, DAD_WTR, $cmd = 'adb -k /vmunix /dev/mem')
  186.     || die "open2 of $cmd failed: $!";
  187.  
  188. # eat first three lines of adb noise
  189. # fourth (and prompts) aren't printed in pipes
  190. for $lines (1..3) {
  191.     die "error reading adb pipe" unless defined($_ = <DAD_RDR>);
  192.  
  193. # get all the code we need to feed the hungry adb
  194. #
  195. @commands = @code{@ARGV};  
  196. #           ^^^^^^^^^^^^^^
  197. # this means ($code{$ARGV[0],$code{$ARGV[1], ...})
  198.  
  199. while (1) {
  200.     print DAD_WTR join("\n", @commands), "\n";
  201.     for ($count = @commands; $count; $count--) {
  202.     &REAPER() unless defined($_ = <DAD_RDR>);
  203.     split;
  204.     print $_[1], "\t\t";
  205.     } 
  206.     print "\n";
  207.     sleep $snooze;
  208. }
  209.  
  210. sub usage {
  211.     $winsize = "\0" x 8;
  212.     $TIOCGWINSZ = 0x40087468;  # should be require 'sys/ioctl.pl';
  213.  
  214.     if (ioctl(STDERR, $TIOCGWINSZ, $winsize)) { 
  215.     ($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
  216.     } else {
  217.     $col = 80;
  218.     } 
  219.  
  220.     $arrows = ('<' x ($col - 25));
  221.  
  222.     eval "format STDERR = \nValid symbols are: ^" .
  223.         $arrows . 
  224.         "\n\$symbols\n~~                 ^" . 
  225.         $arrows . 
  226.         "\n\$symbols\n.\n";
  227.  
  228.     select(STDERR);
  229.  
  230.  
  231.     @keys = sort keys %code;
  232.     for (@keys) {
  233.     s/^/"/;
  234.     s/$/"/;
  235.     } 
  236.     $symbols = join(", ", @keys);
  237.  
  238.     print "usage: $0 [-sleep] symbol ...\n";
  239.     write;
  240.     exit 1;
  241.  
  242. # &open2: tom christiasen, <tchrist@convex.com>
  243. #
  244. #
  245. # usage: $pid = open2('rdr', 'wtr', 'some cmd and args');
  246. #
  247. # spawn the given $cmd and connect $rdr for
  248. # reading and $wtr for writing.  return pid
  249. # of child, or 0 on failure.  
  250. # WARNING: this is dangerous, as you may block forever
  251. # unless you are very careful.  
  252. # $wtr is left unbuffered.
  253. # abort program if
  254. #    rdr or wtr are null
  255. #     pipe or fork or exec fails
  256.  
  257. sub open2 {
  258.     local($dad_rdr, $dad_wtr, $cmd) = @_;
  259.  
  260.     local($kid_rdr) = 'open2_fh00';
  261.     local($kid_wtr) = 'open2_fh01';
  262.     local($kidpid);
  263.  
  264.     $dad_rdr ne ''         || die "open2: rdr should not be null";
  265.     $dad_wtr ne ''         || die "open2: wtr should not be null";
  266.     pipe($dad_rdr, $kid_wtr)     || die "open2: pipe 1 failed: $!";
  267.     pipe($kid_rdr, $dad_wtr)     || die "open2: pipe 2 failed: $!";
  268.  
  269.     if (($kidpid = fork) < 0) {
  270.     die "open2: fork failed: $!";
  271.     } elsif ($kidpid == 0) {
  272.     close $dad_rdr; 
  273.     close $dad_wtr;
  274.     open(STDIN,  ">&$kid_rdr");
  275.     open(STDOUT, ">&$kid_wtr");
  276.     exec $cmd;
  277.     die "open2: exec of $cmd failed";   
  278.     } 
  279.  
  280.     close $kid_rdr; 
  281.     close $kid_wtr;
  282.  
  283.     select((select($dad_wtr), $| = 1)[0]);
  284.  
  285.     $kidpid;
  286. }
  287.