Você está na página 1de 14

Using kstat From Within

a Program in the SolarisTM OS

Rick Weisner
Sun Microsystems, Inc.
March 2007
Copyright © 2007 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights
reserved.

U.S. Government Rights - Commercial software. Government users are subject to the Sun Microsystems, Inc.
standard license agreement and applicable provisions of the FAR and its supplements. Use is subject to license terms.
This distribution may include materials developed by third parties.

Parts of the product may be derived from Berkeley BSD systems, licensed from the University of California. UNIX is
a registered trademark in the U.S. and in other countries, exclusively licensed through X/Open Company, Ltd.
X/Open is a registered trademark of X/Open Company, Ltd.

Sun, Sun Microsystems, the Sun logo, Solaris, and Java are trademarks or registered trademarks of Sun
Microsystems, Inc. in the U.S. and other countries.

This product is covered and controlled by U.S. Export Control laws and may be subject to the export or import laws
in other countries. Nuclear, missile, chemical biological weapons or nuclear maritime end uses or end users, whether
direct or indirect, are strictly prohibited. Export or reexport to countries subject to U.S. embargo or to entities
identified on U.S. export exclusion lists, including, but not limited to, the denied persons and specially designated
nationals lists is strictly prohibited.

DOCUMENTATION IS PROVIDED "AS IS" AND ALL EXPRESS OR IMPLIED CONDITIONS,


REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO THE
EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.

Using kstat From Within a Program in the Solaris OS 2


Table of Contents
Overview....................................................................................................................................................4
Examples....................................................................................................................................................4
1. Walking Through All the kstat.......................................................................................................4
2. Getting NIC kstat Output Using the JavaTM Platform.....................................................................6
Conclusion...............................................................................................................................................13

Using kstat From Within a Program in the Solaris OS 3


Overview

Working in Sun's Adoption Systems Practice for the Solaris 10 OS, I do performance analysis and
support software development in the U.S. Frequently, during the course of my work, I run across
situations in which customers are using system() to execute a script that uses awk, perf, grep,
cut, and so on to extract various operating system metrics of interest. The numerous forks and execs
are expensive and harm performance. I usually suggest using the libkstat APIs to determine the
desired metrics from within the program code. I am often asked to provide examples on how to use the
kstat APIs. What follows is a discussion of a series of examples on how to use the libkstat APIs.

Kernel Statistics, or kstats, have been in the Solaris Operating System for some time. Whenever
vmstat, iostat, or mpstat are used, the kstats in the kernel are accessed. In the Solaris 2.6
OS, an API embodied in libkstat was made available and in the Solaris 8 OS, a Perl program,
kstat, was written to use the module.

Examples

1. Walking Through All the kstat


The first program I will discuss is designed to go through the kstats linearly and extract information.
My commentary is identified by //RCW:.

The next section of code will illustrate how to get specific kstats through linear search.

#include <kstat.h>
#include <stdio.h>
#include <string.h>
#include <sys/sysinfo.h>
int main(int argc, char *argv[])
{
kstat_ctl_t *kc;
kstat_ctl_t wkc;
kstat_t *ksp;
kstat_t *wksp;
cpu_stat_t rcw_cpu_stat_t;
vminfo_t *rcw_vminfo_t;
kstat_named_t *rcw_kstat_named_t;
char name[KSTAT_STRLEN+1];
char class[KSTAT_STRLEN+1];
char module[KSTAT_STRLEN+1];
kid_t kcid;
uint ix[2];
ulong itot;
double util[CPU_STATES];
int i;
//RCW: Open the chain, kstats are accessible through a linked list.
kc = kstat_open();
// kc is a fully initialized kstat structure.
memcpy(&wkc , kc, sizeof(kstat_ctl_t));
// Make a copy of it.
//RCW: Walk the chain.
for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {

Using kstat From Within a Program in the Solaris OS 4


// Header information
//RCW: kstats are identified by module, instance, class, and name.
strncpy(name, ksp->ks_name, KSTAT_STRLEN);
strncpy(class, ksp->ks_class, KSTAT_STRLEN);
strncpy(module, ksp->ks_module, KSTAT_STRLEN);
class[KSTAT_STRLEN] = '\0';
name[KSTAT_STRLEN] = '\0';
fprintf(stderr,"found ks_name = %s, ks_class = %s, ks_instance = %d ks_module =
%s , ndata records= %u , ks_data_size =%u ks_type=%u \n", name, class, ksp->ks_instance,
module, ksp->ks_ndata, ksp->ks_data_size, ksp->ks_type);
//RCW: Named value pairs
if (ksp->ks_type == KSTAT_TYPE_NAMED)
{
fprintf(stderr,"ks_name = %s, ks_class = %s, ks_instance = %d ks_module = %s ,
ndata records= %u , ks_data_size =%u ks_type=%u \n", ksp->ks_name, class, ksp->ks_instance,
module, ksp->ks_ndata, ksp->ks_data_size, ksp->ks_type);
wksp = ksp;
// Copy kstat ptr.
//RCW: Read into kcid from kstat ptr wksp and control structure wkc.
kcid = kstat_read(&wkc, wksp, NULL);
if ( kcid == -1 )
{
fprintf(stderr,"error reading kstats \n");
}
// Save ptr to ks data.
rcw_kstat_named_t = wksp->ks_data;
//RCW: There are ks_ndata data structures.
for ( i = 0 ; i<ksp->ks_ndata; i++)
{
rcw_kstat_named_t->name[KSTAT_STRLEN-1] = '\0';
if ( rcw_kstat_named_t->data_type == KSTAT_DATA_CHAR)
{
rcw_kstat_named_t->value.c[15] = '\0';
fprintf(stderr,"kstat_named_t_name = %s type = %x value = %c
\n", rcw_kstat_named_t->name, rcw_kstat_named_t->data_type, rcw_kstat_named_t->value.c);
}
else if ( rcw_kstat_named_t->data_type == KSTAT_DATA_INT32)
{
fprintf(stderr,"kstat_named_t_name = %s type = %x value = %d
\n", rcw_kstat_named_t->name, rcw_kstat_named_t->data_type, rcw_kstat_named_t->value.i32);
}
else if ( rcw_kstat_named_t->data_type == KSTAT_DATA_UINT32)
{
fprintf(stderr,"kstat_named_t_name = %s type = %x value = %u
\n", rcw_kstat_named_t->name, rcw_kstat_named_t->data_type, rcw_kstat_named_t->value.ui32);
}
else if ( rcw_kstat_named_t->data_type == KSTAT_DATA_INT64)
{
memcpy(ix, &(rcw_kstat_named_t->value.i64), 8);
fprintf(stderr,"kstat_named_t_name = %s type = %x long value = %l
\n", rcw_kstat_named_t->name, rcw_kstat_named_t->data_type, rcw_kstat_named_t->value.i64);
}
else if ( rcw_kstat_named_t->data_type == KSTAT_DATA_UINT64)
{
memcpy(ix, &(rcw_kstat_named_t->value.ui64), 8);
fprintf(stderr,"kstat_named_t_name = %s type = %x ulong value =
%ul \n", rcw_kstat_named_t->name, rcw_kstat_named_t->data_type, rcw_kstat_named_t-
>value.i64);
}
rcw_kstat_named_t++;
}
}
//RCW: In addition to named,value paired data, we have raw data.
//RCW: With raw data you must know what to expect.

Using kstat From Within a Program in the Solaris OS 5


if (ksp->ks_type == KSTAT_TYPE_RAW)
{
fprintf(stderr,"ks_name = %s, ks_class = %s, ks_instance = %d ks_module = %s ,
ndata records= %u , ks_data_size =%u ks_type=%u \n", name, class, ksp->ks_instance, module,
ksp->ks_ndata, ksp->ks_data_size, ksp->ks_type);
if ( strcmp(module,"cpu_stat") == 0 )
{
fprintf(stderr,"reading kstats \n");
wksp = ksp;
//RCW: Read the data corresponding to the pointer.
//RCW: One must know that cpu_stat modules deliver cpu_stat_t data.
kcid = kstat_read(&wkc, wksp, &rcw_cpu_stat_t);
if ( kcid == -1 )
{
fprintf(stderr,"error reading kstats \n");
}
fprintf(stderr," rcw_cpu_stat_t cpu idle= %u , user= %u, sys=%u,
wait=%u , \n", rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_IDLE] ,
rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_USER] , rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_KERNEL] ,
rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_WAIT] );
itot = rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_IDLE] +
rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_USER] + rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_KERNEL] +
rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_WAIT] ;
fprintf(stderr," rcw_cpu_stat_t total %u \n",itot );
util[CPU_IDLE] =
1.0l*rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_IDLE]/itot*1.0l ;
util[CPU_USER] =
1.0l*rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_USER]/itot*1.0l ;
util[CPU_KERNEL] =
1.0l*rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_KERNEL]/itot*1.0l ;
util[CPU_WAIT] =
1.0l*rcw_cpu_stat_t.cpu_sysinfo.cpu[CPU_WAIT]/itot*1.0l ;
fprintf(stderr," rcw_cpu_stat_t cpu idle= %lf , user= %lf, sys=%lf,
wait=%lf , \n", util[CPU_IDLE] , util[CPU_USER], util[CPU_KERNEL], util[CPU_WAIT]);
}
if ( strcmp(module,"unix") == 0 )
{
fprintf(stderr,"reading kstats \n");
wksp = ksp;
kcid = kstat_read(&wkc, wksp, NULL);
if ( kcid == -1 )
{
fprintf(stderr,"error reading kstats \n");
}
rcw_vminfo_t = wksp->ks_data;
//RCW: UNIX modules deliver vminfo data.
fprintf(stderr," rcw_vminfo freemem= %lu , swap_resv= %lu,
swap_alloc=%lu, swap_avail=%lu swap_free=%lu \n", rcw_vminfo_t->freemem,rcw_vminfo_t-
>swap_resv,rcw_vminfo_t->swap_alloc,rcw_vminfo_t->swap_avail,rcw_vminfo_t->swap_free);
}
}
}
exit(0);
}

2. Getting NIC kstat Output Using the JavaTM Platform


The next and last example consists of a library that can be called in the Java programming language or
C.

Using kstat From Within a Program in the Solaris OS 6


First the Java language version:
class RcwKstat {
//RCW: Define a native interface to determine the number of network interfaces.
private native int get_number_my_interf();
//RCW: Define a native method to get the total packets transmitted over the interface.
private native long get_my_interf_packet_count(String str);
//RCW: Define a method to get the name corresponding to an interface instance.
private native String get_my_interf_name(int i);
public static void main(String[] args) throws InterruptedException {
int count=0 ;
RcwKstat rk = new RcwKstat();
String people[] = new String[10];
//RCW: Get the number of interfaces.
count = rk.get_number_my_interf();
String my_interf[] = new String[count];
System.out.println("Interface count = "+count);
//RCW: Get the names of the interfaces.
for (int i=0; i<count; i++)
{
my_interf[i] = rk.get_my_interf_name(i);
System.out.println("Interface = "+i+":"+my_interf[i]);
}
//RCW: Loop forever, listing the counts.
while (true)
{
for ( int i=0; i<count; i++)
{
System.out.println(my_interf[i].toString()+":"+rk.get_my_interf_packet
_count(my_interf[i]));
}
Thread.sleep(1000);
}
}
static {
//RCW: Load library librcw_kstat_lib.so.
System.loadLibrary("rcw_kstat_lib");
}
}

Now compile the Java code with javac and build the header file with javah -jni RcwKstat,
and you will get a header file that looks like this:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class RcwKstat */

#ifndef _Included_RcwKstat
#define _Included_RcwKstat
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: RcwKstat
* Method: get_number_my_interf
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_RcwKstat_get_1number_1my_1interf
(JNIEnv *, jobject);

/*
* Class: RcwKstat

Using kstat From Within a Program in the Solaris OS 7


* Method: get_my_interf_packet_count
* Signature: (Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_RcwKstat_get_1my_1interf_1packet_1count
(JNIEnv *, jobject, jstring);

/*
* Class: RcwKstat
* Method: get_my_interf_name
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_RcwKstat_get_1my_1interf_1name
(JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

Next, I discuss the C library.

First the header:


typedef struct rcw_kstat {
long ipackets;
long opackets;
long rbytes;
long obytes;
} rcw_kstat_t;

Now the library:


#include <kstat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include <rcw_kstat_java.h>
#include <RcwKstat.h> //RCW: Generated by javah

extern int errno;

int rcw_get_kstat(rcw_kstat_t *my_kstat, char *if_name) {


// return 0=success, 1=failure
kstat_ctl_t *kc;
kstat_t *rcw_answer;
kstat_named_t *rcw_kstat_named_t;
kid_t rcw_kid;
unsigned long ipackets=0;
unsigned long opackets=0;
unsigned long rbytes=0;
unsigned long obytes=0;
unsigned long snaptime=0;
static int i=0;
{
//RCW: Open the chain.
kc = kstat_open();
/**************************** NIC lookups ****************************/
//RCW: We know the name of the NIC.
//RCW: So we null out module and instance and go straight to the kstat.
rcw_answer = kstat_lookup(kc, NULL , -1 , if_name);

Using kstat From Within a Program in the Solaris OS 8


if ( rcw_answer == NULL)
{
perror("kstat_lookup failed \n");
return(1);
}
//RCW: We are expecting named, value paired data.
if (rcw_answer->ks_type != KSTAT_TYPE_NAMED)
{
fprintf(stderr," Not type NAMED , How can that be %x \n",rcw_answer->ks_type);
return(1);
}
//RCW: Read the data from the pointer.
rcw_kid=kstat_read(kc, rcw_answer, NULL);
if ( rcw_kid == -1)
{
perror("kstat_read failed \n");
return(1);
}
snaptime=rcw_answer->ks_snaptime;
// The parameter "ipackets" is interface-dependent.
//RCW: We can look up the named data we desire without cycling through all the data.
rcw_kstat_named_t=(kstat_named_t *)kstat_data_lookup(rcw_answer,"ipackets");
//RCW: The name ipackets is fairly common but there is no enforced standard among NICs.
//RCW: Making it generic requires looking into each NIC.
if ( rcw_kstat_named_t == NULL)
{
perror("kstat_data_lookup failed ipackets\n");
return(1);
}
switch (rcw_kstat_named_t->data_type)
{
case (KSTAT_DATA_INT32):
case (KSTAT_DATA_UINT32):
case (KSTAT_DATA_INT64):
case (KSTAT_DATA_UINT64):
ipackets=(unsigned long)rcw_kstat_named_t->value.ui64;
break;
default:
fprintf(stderr,"Invalid data_type %lx for ipackets \n",
rcw_kstat_named_t->data_type);
return(1);
}
// the parameter "ipackets64" is interface dependent
rcw_kstat_named_t=(kstat_named_t *)kstat_data_lookup(rcw_answer,"ipackets64");
if ( rcw_kstat_named_t != NULL)
{
switch (rcw_kstat_named_t->data_type)
{
case (KSTAT_DATA_INT32):
case (KSTAT_DATA_UINT32):
case (KSTAT_DATA_INT64):
case (KSTAT_DATA_UINT64):
ipackets=ipackets+(unsigned long)rcw_kstat_named_t->value.ui64;
break;
default:
fprintf(stderr,"Invalid data_type 0x for ipackets64 \n",
rcw_kstat_named_t->data_type);
return(1);
}
}
// the parameter "opackets" is interface dependent
rcw_kstat_named_t=(kstat_named_t *)kstat_data_lookup(rcw_answer,"opackets");
if ( rcw_kstat_named_t == NULL)
{

Using kstat From Within a Program in the Solaris OS 9


perror("kstat_data_lookup failed opackets \n");
return(1);
}
switch (rcw_kstat_named_t->data_type)
{
case (KSTAT_DATA_INT32):
case (KSTAT_DATA_UINT32):
case (KSTAT_DATA_INT64):
case (KSTAT_DATA_UINT64):
opackets=(unsigned long)rcw_kstat_named_t->value.ui64;
break;
default:
fprintf(stderr,"Invalid data_type 0x for opackets \n",
rcw_kstat_named_t->data_type);
return(1);
}
// the parameter "opackets64" is interface dependent
rcw_kstat_named_t=(kstat_named_t *)kstat_data_lookup(rcw_answer,"opackets64");
if ( rcw_kstat_named_t != NULL)
{
switch (rcw_kstat_named_t->data_type)
{
case (KSTAT_DATA_INT32):
case (KSTAT_DATA_UINT32):
case (KSTAT_DATA_INT64):
case (KSTAT_DATA_UINT64):
opackets=opackets+(unsigned long)rcw_kstat_named_t->value.ui64;
break;
default:
fprintf(stderr,"Invalid data_type 0x for opackets64 \n",
rcw_kstat_named_t->data_type);
return(1);
}
}
// the parameter "rbytes" is interface dependent
rcw_kstat_named_t=(kstat_named_t *)kstat_data_lookup(rcw_answer,"rbytes");
if ( rcw_kstat_named_t != NULL)
{
switch (rcw_kstat_named_t->data_type)
{
case (KSTAT_DATA_INT32):
case (KSTAT_DATA_UINT32):
case (KSTAT_DATA_INT64):
case (KSTAT_DATA_UINT64):
rbytes=(unsigned long)rcw_kstat_named_t->value.ui64;
break;
default:
fprintf(stderr,"Invalid data_type 0x for rbytes \n",
rcw_kstat_named_t->data_type);
return(1);
}
}
// the parameter "rbytes64" is interface dependent
rcw_kstat_named_t=(kstat_named_t *)kstat_data_lookup(rcw_answer,"rbytes64");
if ( rcw_kstat_named_t != NULL)
{
switch (rcw_kstat_named_t->data_type)
{
case (KSTAT_DATA_INT32):
case (KSTAT_DATA_UINT32):
case (KSTAT_DATA_INT64):
case (KSTAT_DATA_UINT64):
rbytes=rbytes+(unsigned long)rcw_kstat_named_t->value.ui64;
break;

Using kstat From Within a Program in the Solaris OS 10


default:
fprintf(stderr,"Invalid data_type 0x for rbytes64 \n",
rcw_kstat_named_t->data_type);
return(1);
}
}
// the parameter "obytes" is interface dependent
rcw_kstat_named_t=(kstat_named_t *)kstat_data_lookup(rcw_answer,"obytes");
if ( rcw_kstat_named_t != NULL)
{
switch (rcw_kstat_named_t->data_type)
{
case (KSTAT_DATA_INT32):
case (KSTAT_DATA_UINT32):
case (KSTAT_DATA_INT64):
case (KSTAT_DATA_UINT64):
obytes=(unsigned long)rcw_kstat_named_t->value.ui64;
break;
default:
fprintf(stderr,"Invalid data_type 0x for obytes \n",
rcw_kstat_named_t->data_type);
return(1);
}
}
// the parameter "obytes64" is interface dependent
rcw_kstat_named_t=(kstat_named_t *)kstat_data_lookup(rcw_answer,"obytes64");
if ( rcw_kstat_named_t != NULL)
{
switch (rcw_kstat_named_t->data_type)
{
case (KSTAT_DATA_INT32):
case (KSTAT_DATA_UINT32):
case (KSTAT_DATA_INT64):
case (KSTAT_DATA_UINT64):
obytes=obytes+(unsigned long)rcw_kstat_named_t->value.ui64;
break;
default:
fprintf(stderr,"Invalid data_type 0x for obytes64 \n",
rcw_kstat_named_t->data_type);
return(1);
}
}
my_kstat->ipackets=ipackets ;
my_kstat->opackets=opackets ;
my_kstat->rbytes=rbytes ;
my_kstat->obytes=obytes ;

/************************ RESTART **************************/


kstat_close(kc);
}
return(0);
}
//RCW: I used a few globals. I require you to get the number of interfaces and their names.
//RCW: Then you can get the packets counts as you desire.
int number_of_interfaces=0;
char *interface_names=NULL;
#define MAX_IF_NAME_SZ 10
int MAX_IF_NAMES=10;
int CURRENT_IF=-1;
//RCW: Get number of interfaces and store a global array of their names.
int get_count_ifs()
{
kstat_ctl_t *kc;
kstat_t *ksp;

Using kstat From Within a Program in the Solaris OS 11


kstat_named_t *rcw_kstat_named_t;
char name[KSTAT_STRLEN+1];
char class[KSTAT_STRLEN+1];
char module[KSTAT_STRLEN+1];
kid_t kcid;
int i;
char if_name[80];

if (interface_names != NULL)
{
free(interface_names);
}
interface_names = (char *) malloc( MAX_IF_NAMES*MAX_IF_NAME_SZ);
kc = kstat_open();
// fully initialized kstat structure.
// make a copy of it
// walk the chain
for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
// header information
strncpy(name, ksp->ks_name, KSTAT_STRLEN);
strncpy(class, ksp->ks_class, KSTAT_STRLEN);
strncpy(module, ksp->ks_module, KSTAT_STRLEN);
class[KSTAT_STRLEN] = '\0';
name[KSTAT_STRLEN] = '\0';
//RCW: Interfaces are in the net class.
if ( strcmp(class,"net") == 0 )
{
sprintf(if_name,"%s%d",module,ksp->ks_instance);
//RCW: If in the netclass and the name is the module+instance, you have an interface kstat.
if ( strcmp(if_name, ksp->ks_name) == 0 )
{
number_of_interfaces++;
if ( number_of_interfaces > MAX_IF_NAMES )
{
MAX_IF_NAMES = MAX_IF_NAMES + 10;
interface_names = (char *) realloc( interface_names,
MAX_IF_NAMES*MAX_IF_NAME_SZ);
}
strcpy(&interface_names[(number_of_interfaces-1)*MAX_IF_NAME_SZ],
if_name);
}
}
}
return(number_of_interfaces);
}
char *return_this_interface(int if_index)
{
if ( number_of_interfaces == 0 ) get_count_ifs();
if ( if_index > number_of_interfaces -1 ) return(NULL);
return(&interface_names[if_index*MAX_IF_NAME_SZ]);
}
//RCW: What follows are the Java hooks.
JNIEXPORT jint JNICALL Java_RcwKstat_get_1number_1my_1interf(JNIEnv *env, jobject obj)
{
jint if_cnt;
if_cnt = get_count_ifs();
//RCW: Native types are easy.
return(if_cnt);
}
JNIEXPORT jlong JNICALL Java_RcwKstat_get_1my_1interf_1packet_1count
(JNIEnv *env, jobject obj, jstring if_name){
rcw_kstat_t my_kstat;
int ret;
const char *str;

Using kstat From Within a Program in the Solaris OS 12


//RCW: Convert Java unicode string to a char array.
str = (*env)->GetStringUTFChars(env, if_name, NULL);
if (str == NULL) {
return -1; /* OutOfMemoryError already thrown */
}
ret=rcw_get_kstat(&my_kstat, (char *)str) ;
if ( ret != 0)
return -1;
//RCW: We do not want a memory leak.
(*env)->ReleaseStringUTFChars(env, if_name, str);
return(my_kstat.ipackets + my_kstat.opackets);
}
JNIEXPORT jstring JNICALL Java_RcwKstat_get_1my_1interf_1name
(JNIEnv * env, jobject obj, jint if_index){
char * my_if_name;
my_if_name=return_this_interface((int) if_index);
if ( my_if_name == NULL ){
return NULL;
}
//RCW: Change char array to Java string before return.
return (*env)->NewStringUTF(env, my_if_name);
}

Just for completeness, here is the Makefile:


all: RcwKstat.class librcw_kstat_lib.so rcwtest librcwkstat.so rcw_main rcwktest

RcwKstat.class: rcw_kstat.java
javac rcw_kstat.java
javah -jni RcwKstat

librcw_kstat_lib.so: RcwKstat.h rcw_kstat_java.h rcw_kstat_lib.c


cc -g -I. -I/usr/java/include -I/usr/java/include/solaris -G rcw_kstat_lib.c -o
librcw_kstat_lib.so -lkstat

rcwtest: rcwtest.c
cc -g rcwtest.c -o rcwtest -lkstat

librcwkstat.so: rcw_kstat_ex.c rcw_kstat_ex.h


cc -g -I. -G rcw_kstat_ex.c -o librcwkstat.so -lkstat

rcw_main: librcwkstat.so rcw_main.c


cc -g -I. rcw_main.c -o rcw_main -L. -lrcwkstat

rcwktest: rcwktest.c
cc -g rcwktest.c -o rcwktest -lkstat

clean:
rm rcwktest rcw_main *.so *.class RcwKstat* rcwtest

Conclusion

For performance reasons, avoid using the system() call to run a script or external program. Use the
appropriate APIs to make your code faster, cleaner, and better.

I am interested in comments, questions, and interesting problems. Send them all to


rick.weisner@sun.com.

Using kstat From Within a Program in the Solaris OS 13


Licensing Information
Unless otherwise specified, the use of this software is authorized pursuant to the terms of the license found at
http://developers.sun.com/berkeley_license.html

Using kstat From Within a Program in the Solaris OS 14