Académique Documents
Professionnel Documents
Culture Documents
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.
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
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) {
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
/*
* 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
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;
RcwKstat.class: rcw_kstat.java
javac rcw_kstat.java
javah -jni RcwKstat
rcwtest: rcwtest.c
cc -g rcwtest.c -o rcwtest -lkstat
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.