GTop Library Project Documentation
Martin
Baulig
martin@home-of-linux.org
1998
Martin Baulig
This documentation is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
For more details see the file COPYING in the source
distribution of LibGTop.
Introduction
About the GTop Library Project
On some systems like DEC OSF/1).
Of cause making a program that uses some toolkit like
Because of this, some kind of server is needed that reada some
commands from standard input and dumps the requested information
to standard output. When written in a secure manner, it can be
SUID root on systems where this is needed.
Any program such as
This is what the
Project Overview
The following steps have to be taken:
Interface Design
First, it is necessary to collect all sorts of information
that can be returned from the library and design some C
structures to hold them. Also, there has to be some method
to find out which elements are supported by the operating
system and which are not.
These C structures and definitions are then put in some
header files which are shared between server and client.
The idea behind this is that if they both use the same
header files - and thus the same interface - programs can
be linked directly with the server library on systems where
this is supported (where the server does not need any
priviledges such as under
Server Implementation
After the general interface is designed, the server part of
the library can be written. We will put both the server and
the client code in two distinct libraries.
Client Implementation
As the next step, we can implement the client side library.
This library will open a pipe to the server, pass it the
request as input and parse its output.
Rewriting existing applications
At this point, the library is ready for use. We can now
begin to rewrite existing applications to use it (or even
write some very new applications).
Porting
As the very last step - once everything is running under
During development, I'll start under DEC OSF/1 V3.0/3.2.
Feedback
Please feel free to contact the author,
Martin Baulig
if you have any comments.
Getting Started
Using the Guile Interface
In examples/third there is a simple guile
interpreter.
On Linux systems, you should use the third_linux
executable, this is statically linked with the system dependent library
and works without installing the server first.
Let's start with a simple example:
$ ./third
guile> (glibtop-get-cpu)
(1107488 39049 0 21981 1046458)
guile> (quit)
Fine, this is our current CPU usage, but what do this five numbers
really mean? Well, of cause one can look a the C header file:
typedef struct _glibtop_cpu glibtop_cpu;
struct _glibtop_cpu
{
unsigned long flags,
total, /* GLIBTOP_CPU_TOTAL */
user, /* GLIBTOP_CPU_USER */
nice, /* GLIBTOP_CPU_NICE */
sys, /* GLIBTOP_CPU_SYS */
idle; /* GLIBTOP_CPU_IDLE */
};
But there's also some easier way:
$ ./third_linux
guile> (glibtop-get-cpu)
(1604151 105343 0 63334 1435474)
guile> (glibtop-names-cpu)
("total" "user" "nice" "sys" "idle")
guile> (quit)
This displays the field names of the C structure
glibtop_cpu. They are not translated into
native language so that one can use guile to generate some C code
that deals with this data.
If you want to use this names in an application program, you should
use the following:
$ ./third_linux
guile> (glibtop-get-cpu)
(1642347 106696 0 63810 1471841)
guile> (glibtop-labels-cpu)
("total" "user" "nice" "sys" "idle")
guile> (quit)
There's no difference? You're correct, while I'm writing this manual,
translations in other languaged have not yet been made and labels have
not been written.
Let's use another example where this is already working:
$ ./third_linux
guile> (glibtop-get-shm_limits)
(33554432 1 128 128 4194304)
guile> (glibtop-names-shm_limits)
("shmmax" "shmmin" "shmmni" "shmseg" "shmall")
guile> (glibtop-labels-shm_limits)
("Max segment size" "Min segment size" "Max number of segments"
"Max shared segments per process" "Max total shared memory")
guile> (quit)
Great! But how can I know what features are currently implemented by the
library? Well, basically there are two ways.
First, you can use
$ ./third_linux
guile> (apropos "glibtop-get")
the-root-module: glibtop-get-cpu #<primitive-procedure glibtop-get-cpu>
the-root-module: glibtop-get-uptime #<primitive-procedure glibtop-get-uptime>
the-root-module: glibtop-get-sysdeps #<primitive-procedure glibtop-get-sysdeps>
the-root-module: glibtop-get-loadavg #<primitive-procedure glibtop-get-loadavg>
the-root-module: glibtop-get-swap #<primitive-procedure glibtop-get-swap>
the-root-module: glibtop-get-proclist #<primitive-procedure glibtop-get-proclist>
the-root-module: glibtop-get-sem_limits #<primitive-procedure glibtop-get-sem_limits>
the-root-module: glibtop-get-msg_limits #<primitive-procedure glibtop-get-msg_limits>
the-root-module: glibtop-get-shm_limits #<primitive-procedure glibtop-get-shm_limits>
the-root-module: glibtop-get-mem #<primitive-procedure glibtop-get-mem>
guile> (quit)
This gives you a basic idea which functions are defined in the library.
But there's also a better way:
$ ./third_linux
guile> (glibtop-get-sysdeps)
(31 127 7 3 1 31 127 1023 3)
guile> (glibtop-names-sysdeps)
("cpu" "mem" "swap" "uptime" "loadavg" "shm_limits" "msg_limits" "sem_limits"
"proclist")
guile> (glibtop-labels-sysdeps)
("CPU Usage" "Memory Usage" "Swap Usage" "System Uptime" "Load Averange"
"Shared Memory Limits" "Message Queue Limits" "Semaphore Set Limits"
"List of running Processes")
guile> (quit)
Back to the glibtop_get_cpu. Here is a nice example
on how you can convert the returned data to percents:
[FIXME: not yet written]
Using system dependent features
Some of the features of the library are only implemented on some systems.
For instance, in our last example:
guile> (glibtop-get-cpu)
(2091847 130894 17 70602 1890334)
Well fine - some process is running with nice now on my system - but in
the last section, we always got zero in the nice
field. When some feature is not implemented on a particular system, it is
set to zero. So how can we find out whether a feature is not implemented on
the current system or whether it is really zero all the time?
This is what the flags member of the C structure
is for. Since theese flags never change during the lifetime of a process,
on can call glibtop_get_sysdeps to get a structure
glibtop_sysdeps containing the
flags members of all currently available features.
The contents of the structure remains constant during the lifetime of a
process.
In guile, on can use glibgtop-get-sysdeps, too:
guile> (glibtop-get-sysdeps)
(31 127 7 3 1 31 127 1023 3)
We already know that the first member of this list corresponds to
glibtop_cpu. So this 31
tells us which features of glibtop_cpu are
implemented on this systems. The binary representation of
31 is 11111. If the lowest bit
of this constant is set, this means that the first list element is
implemented on the current system and so on. If, for instance, the
user member of glibtop_cpu
is not implemented, this constant will be 11101
or 29 in decimal representation.
Using the library in a C program
Well, in C things are a little bit more complicated than in guile.
Let's start with a very simple example:
First steps
#include <glibtop/open.h>
#include <glibtop/close.h>
#include <glibtop/cpu.h>
int
main (int argc, char *argv [])
{
glibtop server;
glibtop_cpu cpu;
glibtop_open (&server, argv [0]);
glibtop_get_cpu (&server, &cpu);
fprintf (stderr, "CPU: %lu, %lu, %lu, %lu, %lu\n",
cpu.total, cpu.user, cpu.nice, cpu.sys, cpu.idle);
glibtop_close (&server);
}
This will print out:
$ ./first_linux
CPU: 2262741, 136828, 17, 72569, 2053327
Make sure to open a connection to the server by a call to
glibtop_open before calling any other function
of the library and to close that connection upon termination by a call to
glibtop_close. Otherwise your program may either
not work correctly or simply dump core.
Using names and labels in C
To dump out the field names of glibtop_cpu:
Dump field names of glibtop_cpu:
#include <glibtop/open.h>
#include <glibtop/close.h>
#include <glibtop/cpu.h>
int
main (int argc, char *argv [])
{
fprintf (stderr, "CPU Names: %s, %s, %s, %s, %s\n",
glibtop_names_cpu [GLIBTOP_CPU_TOTAL],
glibtop_names_cpu [GLIBTOP_CPU_USER],
glibtop_names_cpu [GLIBTOP_CPU_NICE],
glibtop_names_cpu [GLIBTOP_CPU_SYS],
glibtop_names_cpu [GLIBTOP_CPU_IDLE]);
}
Since this are constants, they also work without the server connection.
To dump all members of glibtop_cpu no matter
how many there are:
Dump all members of glibtop_cpu no matter
how many
#include <glibtop/open.h>
#include <glibtop/close.h>
#include <glibtop/cpu.h>
int
main (int argc, char *argv [])
{
int i;
for (i = 0; i < GLIBTOP_MAX_CPU; i++)
fprintf (stderr,"#%d: %s\n", i, glibtop_names_cpu [i]);
}
Finaly, let's dump the internationalized labels:
Dump internationalized labels
#include <glibtop.h>
#include <glibtop/open.h>
#include <glibtop/close.h>
#include <glibtop/cpu.h>
int
main (int argc, char *argv [])
{
int i;
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, GTOPLOCALEDIR);
textdomain (PACKAGE);
for (i = 0; i < GLIBTOP_MAX_CPU; i++)
fprintf (stderr,"#%d: %s\n", i,
gettext (glibtop_labels_cpu [i]));
}
Using system dependent features in C
In C, there are some constants defined in the header files:
#define GLIBTOP_CPU_TOTAL 0
#define GLIBTOP_CPU_USER 1
#define GLIBTOP_CPU_NICE 2
#define GLIBTOP_CPU_SYS 3
#define GLIBTOP_CPU_IDLE 4
The value used in the flags member to indicate
whether some feature is implemented on the current system is always
2 at the power of the corresponding constant.
For instance, if you want to print out the user
field of glibtop_cpu when it's implemented on the
current system, you can use:
Only print user member of
glibtop_cpu when it's implemented
#include <glibtop/open.h>
#include <glibtop/close.h>
#include <glibtop/cpu.h>
int
main (int argc, char *argv [])
{
glibtop server;
glibtop_cpu cpu;
glibtop_open (&server, argv [0]);
glibtop_get_cpu (&server, &cpu);
fprintf (stderr, "CPU: %lu, ", cpu.total);
/* FIXME: is this correct? */
if (cpu.flags & (1 << GLIBTOP_CPU_USER))
fprintf (stderr, "%lu, ", cpu.user);
fprintf (stderr, "%lu, %lu, %lu\n", cpu.nice, cpu.sys, cpu.idle);
glibtop_close (&server);
}
Hacker's Guide
Extending the Library
This section will give you a step by step tutorial on how to extend the
library to add a new feature. It is not yet really complete.