263 lines
6.8 KiB
C
263 lines
6.8 KiB
C
/*
|
|
* Routines for Solaris.
|
|
*
|
|
* Note that this might not work on differnet versions of Solaris. The
|
|
* reason being is that the kstat variables can change from version to
|
|
* version. Read the kvm and kstat man pages to see what Sun says
|
|
* about it. Also there is no 'real' way to find out the implemented
|
|
* kernel variables! There is an undocumented feature to netstat which
|
|
* walks the kstat chain. The output sort of makes sense for kernel
|
|
* hackers. Anyways use 'netstat -k'.
|
|
*
|
|
* The code is GPL'ed. See the asmon COPYING file that comes with the
|
|
* distribution. The only thing I add is that if you use this code
|
|
* and we meet sometime, then you can buy me a beer. Happy monitoring.
|
|
*
|
|
* Eric Davis <ead@pobox.com>
|
|
*/
|
|
|
|
#include <kstat.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <sys/cpuvar.h>
|
|
#include <sys/swap.h>
|
|
#include <sys/param.h>
|
|
|
|
|
|
typedef struct swapent SWAP_ENT_T;
|
|
typedef struct swaptable SWAP_TABLE_T;
|
|
typedef unsigned long ULONG;
|
|
|
|
|
|
static int err
|
|
(
|
|
char * msg
|
|
)
|
|
{
|
|
perror(msg);
|
|
return -1;
|
|
}
|
|
|
|
|
|
int getLoad
|
|
(
|
|
float * load
|
|
)
|
|
{
|
|
kstat_t * ks;
|
|
kstat_ctl_t * kc;
|
|
kstat_named_t * kn;
|
|
|
|
if ((kc = kstat_open()) == NULL)
|
|
return err("kstat_open");
|
|
|
|
if ((ks = kstat_lookup(kc, "unix", 0, "system_misc")) == NULL)
|
|
return err("kstat_lookup");
|
|
|
|
if (kstat_read(kc, ks, NULL) == -1)
|
|
return err("kstat_read");
|
|
|
|
if ((kn = kstat_data_lookup(ks, "avenrun_1min")) == NULL)
|
|
return err("kstat_data_lookup");
|
|
|
|
if (kstat_close(kc) == -1)
|
|
return err("kstat_close");
|
|
|
|
*load = ((float)kn->value.ul / FSCALE);
|
|
/* printf("load: %2.2f\n\n", *load); */
|
|
return 0;
|
|
}
|
|
|
|
|
|
int getSwap
|
|
(
|
|
ULONG * swapMax,
|
|
ULONG * swapFree
|
|
)
|
|
{
|
|
static char buf[256];
|
|
int i;
|
|
int totalSwapEntries;
|
|
SWAP_TABLE_T * swapTable;
|
|
SWAP_ENT_T * swapEntries;
|
|
|
|
TRY_AGAIN:
|
|
|
|
totalSwapEntries = swapctl(SC_GETNSWP, 0);
|
|
swapTable = (SWAP_TABLE_T *)malloc(sizeof(int) +
|
|
(totalSwapEntries *
|
|
sizeof(SWAP_ENT_T)));
|
|
|
|
swapTable->swt_n = totalSwapEntries;
|
|
for (swapEntries = &(swapTable->swt_ent[0]),
|
|
i = 0; i < totalSwapEntries; i++, swapEntries++)
|
|
{
|
|
swapEntries->ste_path = buf;
|
|
}
|
|
|
|
if (swapctl(SC_LIST, swapTable) == -1)
|
|
{
|
|
/* Retry if our swap table was too small else bail */
|
|
free(swapTable);
|
|
perror("swapctl");
|
|
if (errno == ENOMEM) goto TRY_AGAIN;
|
|
else return -1;
|
|
}
|
|
|
|
for (swapEntries = &(swapTable->swt_ent[0]), *swapMax = *swapFree = 0,
|
|
i = 0; i < totalSwapEntries; i++, swapEntries++)
|
|
{
|
|
if (!(swapEntries->ste_flags & ST_INDEL) &&
|
|
!(swapEntries->ste_flags & ST_DOINGDEL))
|
|
{
|
|
*swapMax += swapEntries->ste_pages;
|
|
*swapFree += swapEntries->ste_free;
|
|
}
|
|
}
|
|
|
|
*swapMax *= sysconf(_SC_PAGESIZE);
|
|
*swapFree *= sysconf(_SC_PAGESIZE);
|
|
/*
|
|
printf("swap max: %ld\nswap free: %ld\nswap used: %ld\n\n",
|
|
*swapMax, *swapFree, (*swapMax - *swapFree));
|
|
*/
|
|
free(swapTable);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int getMem
|
|
(
|
|
ULONG * memMax,
|
|
ULONG * memFree
|
|
)
|
|
{
|
|
kstat_t * ks;
|
|
kstat_ctl_t * kc;
|
|
kstat_named_t * kn;
|
|
|
|
if ((kc = kstat_open()) == NULL)
|
|
return err("kstat_open");
|
|
|
|
if ((ks = kstat_lookup(kc, "unix", 0, "system_pages")) == NULL)
|
|
return err("kstat_lookup");
|
|
|
|
if (kstat_read(kc, ks, NULL) == -1)
|
|
return err("kstat_read");
|
|
|
|
if ((kn = kstat_data_lookup(ks, "physmem")) == NULL)
|
|
return err("kstat_data_lookup");
|
|
|
|
*memMax = (kn->value.ul * sysconf(_SC_PAGESIZE));
|
|
|
|
if ((kn = kstat_data_lookup(ks, "freemem")) == NULL)
|
|
return err("kstat_data_lookup");
|
|
|
|
*memFree = (kn->value.ul * sysconf(_SC_PAGESIZE));
|
|
|
|
if (kstat_close(kc) == -1)
|
|
return err("kstat_close");
|
|
|
|
/*
|
|
printf("mem max: %ld\nmem free: %ld\nmem used: %ld\n\n",
|
|
*memMax, *memFree, (*memMax - *memFree));
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
|
|
int getCPU
|
|
(
|
|
ULONG * cpuIdle,
|
|
ULONG * cpuUser,
|
|
ULONG * cpuKern,
|
|
ULONG * cpuWait,
|
|
ULONG * pageIn,
|
|
ULONG * pageOut,
|
|
ULONG * swapIn,
|
|
ULONG * swapOut
|
|
)
|
|
{
|
|
cpu_stat_t * cpu_stat;
|
|
|
|
ULONG numCPUs;
|
|
int i;
|
|
kstat_t * ks;
|
|
kstat_ctl_t * kc;
|
|
kstat_named_t * kn;
|
|
|
|
if ((kc = kstat_open()) == NULL)
|
|
return err("kstat_open");
|
|
|
|
if ((ks = kstat_lookup(kc, "unix", 0, "system_misc")) == NULL)
|
|
return err("kstat_lookup");
|
|
|
|
if (kstat_read(kc, ks, NULL) == -1)
|
|
return err("kstat_read");
|
|
|
|
if ((kn = kstat_data_lookup(ks, "ncpus")) == NULL)
|
|
return err("kstat_data_lookup");
|
|
|
|
numCPUs = kn->value.ul;
|
|
|
|
cpu_stat = (cpu_stat_t *)malloc(numCPUs * sizeof(cpu_stat_t));
|
|
|
|
for (i = 0, ks = kc->kc_chain; ks != NULL; ks = ks->ks_next)
|
|
{
|
|
if (strncmp(ks->ks_name, "cpu_stat", 8) == 0)
|
|
{
|
|
if (kstat_read(kc, ks, &cpu_stat[i++]) == -1)
|
|
{
|
|
free(cpu_stat);
|
|
return err("kstat_read");
|
|
}
|
|
if (i > numCPUs)
|
|
{
|
|
fprintf(stderr,
|
|
"getCPU: invalid number of cpus in kstat chain\n");
|
|
free(cpu_stat);
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
if (i != numCPUs)
|
|
{
|
|
fprintf(stderr,
|
|
"getCPU: invalid number of cpus in kstat chain\n");
|
|
free(cpu_stat);
|
|
return -1;
|
|
}
|
|
|
|
for (*cpuIdle = *cpuUser = *cpuKern = *cpuWait = 0,
|
|
*pageIn = *pageOut = *swapIn = *swapOut = 0,
|
|
i = 0; i < numCPUs; ++i)
|
|
{
|
|
*cpuIdle += cpu_stat[i].cpu_sysinfo.cpu[CPU_IDLE];
|
|
*cpuUser += cpu_stat[i].cpu_sysinfo.cpu[CPU_USER];
|
|
*cpuKern += cpu_stat[i].cpu_sysinfo.cpu[CPU_KERNEL];
|
|
*cpuWait += cpu_stat[i].cpu_sysinfo.cpu[CPU_WAIT];
|
|
*pageIn += cpu_stat[i].cpu_vminfo.pgpgin;
|
|
*pageOut += cpu_stat[i].cpu_vminfo.pgpgout;
|
|
*swapIn += cpu_stat[i].cpu_vminfo.pgswapin;
|
|
*swapOut += cpu_stat[i].cpu_vminfo.pgswapout;
|
|
}
|
|
|
|
if (kstat_close(kc) == -1)
|
|
{
|
|
free(cpu_stat);
|
|
return err("kstat_close");
|
|
}
|
|
|
|
/*
|
|
printf("num cpus: %ld\ncpu idle: %ld\ncpu user: %ld\ncpu kern: %ld\ncpu wait: %ld\npage in: %ld\npage out: %ld\nswap in: %ld\nswap out: %ld\n\n",
|
|
numCPUs, *cpuIdle, *cpuUser, *cpuKern, *cpuWait,
|
|
*pageIn, *pageOut, *swapIn, *swapOut);
|
|
*/
|
|
free(cpu_stat);
|
|
return 0;
|
|
}
|
|
|