Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using system calls from C, how do I get the utilization of the CPU(s)?

Tags:

c

freebsd

In C on FreeBSD, how does one access the CPU utilization?

I am writing some code to handle HTTP redirects. If the CPU load goes above a threshold on a FReeBSD system, I want to redirect client requests. Looking over the man pages, kvm_getpcpu() seems to be the right answer, but the man pages (that I read) don't document the usage.

Any tips or pointers would be welcome - thanks!


After reading the answers here, I was able to come up with the below. Due to the poor documentation, I'm not 100% sure it is correct, but top seems to agree. Thanks to everyone who answered.

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <unistd.h>

#define CP_USER   0
#define CP_NICE   1
#define CP_SYS    2
#define CP_INTR   3
#define CP_IDLE   4
#define CPUSTATES 5

int main()
{
        long cur[CPUSTATES], last[CPUSTATES];
        size_t cur_sz = sizeof cur;
        int state, i;
        long sum;
        double util;

        memset(last, 0, sizeof last);

        for (i=0; i<6; i++)
        {
                if (sysctlbyname("kern.cp_time", &cur, &cur_sz, NULL, 0) < 0)
                {
                        printf ("Error reading kern.cp_times sysctl\n");
                        return -1;
                }

                sum = 0;
                for (state = 0; state<CPUSTATES; state++)
                {
                        long tmp = cur[state];
                        cur[state] -= last[state];
                        last[state] = tmp;
                        sum += cur[state];
                }

                util = 100.0L - (100.0L * cur[CP_IDLE] / (sum ? (double) sum : 1.0L));
                printf("cpu utilization: %7.3f\n", util);
                sleep(1);
        }

        return 0;
}
like image 565
Edmond Meinfelder Avatar asked Mar 16 '11 17:03

Edmond Meinfelder


1 Answers

From the MAN pages

NAME

kvm_getmaxcpu, kvm_getpcpu -- access per-CPU data

LIBRARY

Kernel Data Access Library (libkvm, -lkvm)

SYNOPSIS

 #include <sys/param.h>
 #include <sys/pcpu.h>
 #include <sys/sysctl.h>
 #include <kvm.h>

 int
 kvm_getmaxcpu(kvm_t *kd);

 void *
 kvm_getpcpu(kvm_t *kd, int cpu);

DESCRIPTION

The kvm_getmaxcpu() and kvm_getpcpu() functions are used to access the per-CPU data of active processors in the kernel indicated by kd. The kvm_getmaxcpu() function returns the maximum number of CPUs supported by the kernel. The kvm_getpcpu() function returns a buffer holding the per- CPU data for a single CPU. This buffer is described by the struct pcpu type. The caller is responsible for releasing the buffer via a call to free(3) when it is no longer needed. If cpu is not active, then NULL is returned instead.

CACHING

These functions cache the nlist values for various kernel variables which are reused in successive calls. You may call either function with kd set to NULL to clear this cache.

RETURN VALUES

On success, the kvm_getmaxcpu() function returns the maximum number of CPUs supported by the kernel. If an error occurs, it returns -1 instead.

On success, the kvm_getpcpu() function returns a pointer to an allocated buffer or NULL. If an error occurs, it returns -1 instead.

If either function encounters an error, then an error message may be retrieved via kvm_geterr(3.)


EDIT

Here's the kvm_t struct:

struct __kvm {
    /*
     * a string to be prepended to error messages
     * provided for compatibility with sun's interface
     * if this value is null, errors are saved in errbuf[]
     */
    const char *program;
    char   *errp;           /* XXX this can probably go away */
    char    errbuf[_POSIX2_LINE_MAX];
    #define ISALIVE(kd) ((kd)->vmfd >= 0)
    int     pmfd;           /* physical memory file (or crashdump) */
    int     vmfd;           /* virtual memory file (-1 if crashdump) */
    int     unused;         /* was: swap file (e.g., /dev/drum) */
    int     nlfd;           /* namelist file (e.g., /kernel) */
    struct kinfo_proc *procbase;
    char   *argspc;         /* (dynamic) storage for argv strings */
    int     arglen;         /* length of the above */
    char    **argv;         /* (dynamic) storage for argv pointers */
    int     argc;           /* length of above (not actual # present) */
    char    *argbuf;        /* (dynamic) temporary storage */
    /*
     * Kernel virtual address translation state.  This only gets filled
     * in for dead kernels; otherwise, the running kernel (i.e. kmem)
     * will do the translations for us.  It could be big, so we
     * only allocate it if necessary.
     */
    struct vmstate *vmst;
};
like image 128
Macmade Avatar answered Sep 29 '22 02:09

Macmade