Linux C程序 获取内存使用率和Cpu占有率,从Top 源码中裁剪移植

/*
 * =====================================================================================
 *
 *       Filename:  util_sysinfo.c
 *
 *    Description:  get cpu load and memory state
 *
 *        Version:  1.0
 *        Created:  2016年01月23日
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Dr. Clement.Huang
 *   Organization:
 *
 * =====================================================================================
 */
#include <sys/types.h>
#include <time.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include "util_sysinfo.h"

//#define DEBUG


#define PROCFS "/proc"

#define NPROCSTATES 7

#define NCPUSTATES 7



#ifdef DEBUG
double load_avg[NUM_AVERAGES];
#endif
/* these are for calculating cpu state percentages */

static long cp_time[NCPUSTATES];
static long cp_old[NCPUSTATES];
static long cp_diff[NCPUSTATES];

/* for calculating the exponential average */

static struct timeval lasttime = { 0, 0 };
static struct timeval timediff = { 0, 0 };
static long elapsed_msecs;


/* these are counters that need to be track */
static unsigned long last_ctxt = 0;
static unsigned long last_intr = 0;
static unsigned long last_newproc = 0;
static unsigned long last_flt = 0;

/* these are for passing data back to the machine independant portion */


/* cpu states name:"user", "nice", "system", "idle", "iowait", "irq", "sirq",*/
static int cpu_states[NCPUSTATES];
/* process states name:"", "run", "sleep", "disk", "zomb", "stop", "swap", */
static int process_states[NPROCSTATES];
/* kernelnames:" ctxsw, ", " flt, ", " intr, ", " newproc",*/
static int kernel_stats[NKERNELSTATS];
/* memorynames:"K used, ", "K free, ", "K shared, ", "K buffers, ", "K cached",*/
static long memory_stats[NMEMSTATS];
/* swapnames:"K used, ", "K free, ", "K cached",*/
static long swap_stats[NSWAPSTATS];




/* useful macros */
#define bytetok(bytes) ((bytes) >> 10)

/* calculate a per-second rate using milliseconds */
#define per_second(n, msec)   (((n) * 1000) / (msec))

/* inline function */
static inline char * skip_ws(const char *p)
{
    while (isspace(*p)) p++;
    return (char *)p;
}

static inline char * skip_token(const char *p)
{
    while (isspace(*p)) p++;
    while (*p && !isspace(*p)) p++;
    return (char *)p;
}


/*
 *  percentages(cnt, out, new, old, diffs) - calculate percentage change
 *    between array "old" and "new", putting the percentages i "out".
 *    "cnt" is size of each array and "diffs" is used for scratch space.
 *    The array "old" is updated on each call.
 *    The routine assumes modulo arithmetic.  This function is especially
 *    useful on BSD mchines for calculating cpu state percentages.
 */
static long percentages(int cnt, int *out, long *new, long *old, long *diffs)
{
    register int i;
    register long change;
    register long total_change;
    register long *dp;
    long half_total;

    /* initialization */
    total_change = 0;
    dp = diffs;

    /* calculate changes for each state and the overall change */
    for (i = 0; i < cnt; i++)
    {
    if ((change = *new - *old) < 0)
    {
        /* this only happens when the counter wraps */
        change = (int)
        ((unsigned long)*new-(unsigned long)*old);
    }
    total_change += (*dp++ = change);
    *old++ = *new++;
    }

    /* avoid divide by zero potential */
    if (total_change == 0)
    {
    total_change = 1;
    }

    /* calculate percentages based on overall change, rounding up */
    half_total = total_change / 2l;
    for (i = 0; i < cnt; i++)
    {
    *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
    }

    /* return the total in case the caller wants to use it */
    return(total_change);
}


void get_system_info(struct system_info *info)
{
    char buffer[4096+1];
    int fd, len;
    char *p;
    struct timeval thistime;
    unsigned long intr = 0;
    unsigned long ctxt = 0;
    unsigned long newproc = 0;
    unsigned long flt = 0;

    /* timestamp and time difference */
    gettimeofday(&thistime, 0);
    timersub(&thistime, &lasttime, &timediff);
    elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000;
    lasttime = thistime;

    /* get load averages */
    if ((fd = open("/proc/loadavg", O_RDONLY)) != -1)
    {
    if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
    {
        buffer[len] = '\0';
        info->load_avg[0] = strtod(buffer, &p);
        info->load_avg[1] = strtod(p, &p);
        info->load_avg[2] = strtod(p, &p);
        p = skip_token(p);            /* skip running/tasks */
        p = skip_ws(p);
        if (*p)
        {
          info->last_pid = atoi(p);
        }
        else
        {
          info->last_pid = -1;
        }
    }
    close(fd);
    }


    /* get the cpu time info */
    if ((fd = open("/proc/stat", O_RDONLY)) != -1)
    {
    if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
    {
        buffer[len] = '\0';
        p = skip_token(buffer);            /* "cpu" */
        cp_time[0] = strtoul(p, &p, 0);
        cp_time[1] = strtoul(p, &p, 0);
        cp_time[2] = strtoul(p, &p, 0);
        cp_time[3] = strtoul(p, &p, 0);
        cp_time[4] = strtoul(p, &p, 0);
        cp_time[5] = strtoul(p, &p, 0);
        cp_time[6] = strtoul(p, &p, 0);
        /* convert cp_time counts to percentages */
        percentages(NCPUSTATES, cpu_states, cp_time, cp_old, cp_diff);

        /* get the rest of it */
        p = strchr(p, '\n');
        while (p != NULL)
        {
        p++;
        if (strncmp(p, "intr ", 5) == 0)
        {
            p = skip_token(p);
            intr = strtoul(p, &p, 10);
        }
        else if (strncmp(p, "ctxt ", 5) == 0)
        {
            p = skip_token(p);
            ctxt = strtoul(p, &p, 10);
        }
        else if (strncmp(p, "processes ", 10) == 0)
        {
            p = skip_token(p);
            newproc = strtoul(p, &p, 10);
        }

        p = strchr(p, '\n');
        }

        kernel_stats[KERNELINTR] = per_second(intr - last_intr, elapsed_msecs);
        kernel_stats[KERNELCTXT] = per_second(ctxt - last_ctxt, elapsed_msecs);
        kernel_stats[KERNELNEWPROC] = per_second(newproc - last_newproc, elapsed_msecs);
        last_intr = intr;
        last_ctxt = ctxt;
        last_newproc = newproc;
    }
    close(fd);
    }

    /* get system wide memory usage */
    if ((fd = open("/proc/meminfo", O_RDONLY)) != -1)
    {
    char *p;
    int mem = 0;
    int swap = 0;
    unsigned long memtotal = 0;
    unsigned long memfree = 0;
    unsigned long swaptotal = 0;

    if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
    {
        buffer[len] = '\0';
        p = buffer-1;

        /* iterate thru the lines */
        while (p != NULL)
        {
        p++;
        if (p[0] == ' ' || p[0] == '\t')
        {
            /* skip */
        }
        else if (strncmp(p, "Mem:", 4) == 0)
        {
            p = skip_token(p);            /* "Mem:" */
            p = skip_token(p);            /* total memory */
            memory_stats[MEMUSED] = strtoul(p, &p, 10);
            memory_stats[MEMFREE] = strtoul(p, &p, 10);
            memory_stats[MEMSHARED] = strtoul(p, &p, 10);
            memory_stats[MEMBUFFERS] = strtoul(p, &p, 10);
            memory_stats[MEMCACHED] = strtoul(p, &p, 10);
            memory_stats[MEMUSED] = bytetok(memory_stats[MEMUSED]);
            memory_stats[MEMFREE] = bytetok(memory_stats[MEMFREE]);
            memory_stats[MEMSHARED] = bytetok(memory_stats[MEMSHARED]);
            memory_stats[MEMBUFFERS] = bytetok(memory_stats[MEMBUFFERS]);
            memory_stats[MEMCACHED] = bytetok(memory_stats[MEMCACHED]);
            mem = 1;
        }
        else if (strncmp(p, "Swap:", 5) == 0)
        {
            p = skip_token(p);            /* "Swap:" */
            p = skip_token(p);            /* total swap */
            swap_stats[SWAPUSED] = strtoul(p, &p, 10);
            swap_stats[SWAPFREE] = strtoul(p, &p, 10);
            swap_stats[SWAPUSED] = bytetok(swap_stats[SWAPUSED]);
            swap_stats[SWAPFREE] = bytetok(swap_stats[SWAPFREE]);
            swap = 1;
        }
        else if (!mem && strncmp(p, "MemTotal:", 9) == 0)
        {
            p = skip_token(p);
            memtotal = strtoul(p, &p, 10);
        }
        else if (!mem && memtotal > 0 && strncmp(p, "MemFree:", 8) == 0)
        {
            p = skip_token(p);
            memfree = strtoul(p, &p, 10);
            memory_stats[MEMUSED] = memtotal - memfree;
            memory_stats[MEMFREE] = memfree;
        }
        else if (!mem && strncmp(p, "MemShared:", 10) == 0)
        {
            p = skip_token(p);
            memory_stats[MEMSHARED] = strtoul(p, &p, 10);
        }
        else if (!mem && strncmp(p, "Buffers:", 8) == 0)
        {
            p = skip_token(p);
            memory_stats[MEMBUFFERS] = strtoul(p, &p, 10);
        }
        else if (!mem && strncmp(p, "Cached:", 7) == 0)
        {
            p = skip_token(p);
            memory_stats[MEMCACHED] = strtoul(p, &p, 10);
        }
        else if (!swap && strncmp(p, "SwapTotal:", 10) == 0)
        {
            p = skip_token(p);
            swaptotal = strtoul(p, &p, 10);
        }
        else if (!swap && swaptotal > 0 && strncmp(p, "SwapFree:", 9) == 0)
        {
            p = skip_token(p);
            memfree = strtoul(p, &p, 10);
            swap_stats[SWAPUSED] = swaptotal - memfree;
            swap_stats[SWAPFREE] = memfree;
        }
        else if (!mem && strncmp(p, "SwapCached:", 11) == 0)
        {
            p = skip_token(p);
            swap_stats[SWAPCACHED] = strtoul(p, &p, 10);
        }

        /* move to the next line */
        p = strchr(p, '\n');
        }
    }
    close(fd);
    }

    /* get vm related stuff */
    if ((fd = open("/proc/vmstat", O_RDONLY)) != -1)
    {
    char *p;

    if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
    {
        buffer[len] = '\0';
        p = buffer;

        /* iterate thru the lines */
        while (p != NULL)
        {
        if (strncmp(p, "pgmajfault ", 11) == 0)
        {
            p = skip_token(p);
            flt = strtoul(p, &p, 10);
            kernel_stats[KERNELFLT] = per_second(flt - last_flt, elapsed_msecs);
            last_flt = flt;
            break;
        }

        /* move to the next line */
        p = strchr(p, '\n');
        p++;
        }
    }
    close(fd);
    }

    /* set arrays and strings */
    info->cpustates = cpu_states;
    info->memory = memory_stats;
    info->swap = swap_stats;
    info->kernel = kernel_stats;

#ifdef DEBUG
    load_avg[0] = info->load_avg[0];
    load_avg[0] = info->load_avg[0];
    load_avg[0] = info->load_avg[0];
#endif
}


#ifdef DEBUG

int main(int argc, char *argv[])
{
    struct system_info system_info;

    chdir(PROCFS);

    get_system_info(&system_info);

    printf("memused %ld;memfree %ld;memshared %ld;membuffers %ld;memcached %ld;\n",memory_stats[MEMUSED],memory_stats[MEMFREE],memory_stats[MEMSHARED],\
    memory_stats[MEMSHARED],memory_stats[MEMCACHED]);

    printf("user %4.1f%%,sys %4.1f%%,nice %4.1f%%,idle %4.1f%%,iowait %4.1f%%;\n",((float)cpu_states[0])/10,\
    ((float)cpu_states[1])/10,((float)cpu_states[2])/10,((float)cpu_states[3])/10,((float)cpu_states[4])/10);

    printf("load average: %.2lf, %.2lf, %.2lf\n",load_avg[0],load_avg[1],load_avg[2]);

    return 0;
}

#endif


/*
 * =====================================================================================
 *
 *       Filename:  util_sysinfo.h
 *
 *    Description:  get cpu load and memory state
 *
 *        Version:  1.0
 *        Created:  2016年01月23日
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Dr. Clement.Huang
 *   Organization:
 *
 * =====================================================================================
 */

#ifndef __UTIL_SYSINFO_H__
#define __UTIL_SYSINFO_H__


#define KERNELCTXT    0
#define KERNELFLT     1
#define KERNELINTR    2
#define KERNELNEWPROC 3
#define NKERNELSTATS  4

#define MEMUSED    0
#define MEMFREE    1
#define MEMSHARED  2
#define MEMBUFFERS 3
#define MEMCACHED  4
#define NMEMSTATS  5

#define SWAPUSED   0
#define SWAPFREE   1
#define SWAPCACHED 2
#define NSWAPSTATS 3


#define NUM_AVERAGES    3


struct system_info
{
    int    last_pid;
    double load_avg[NUM_AVERAGES];
    int    p_total;
    int    P_ACTIVE;     /* number of procs considered "active" */
    int    *procstates;
    int    *cpustates;
    int    *kernel;
    long   *memory;
    long   *swap;
};

void get_system_info(struct system_info *info);



#endif


猜你喜欢

转载自blog.csdn.net/qq_28086637/article/details/52200645