본문 바로가기

Linux

procfs system

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <nlist.h>
#include <kvm.h>
#include <sys/proc.h>
#include <sys/procfs.h>
#include <sys/var.h>
#include <sys/cpuvar.h>
#include <sys/file.h>
#include <sys/swap.h>
#include <kstat.h>


/* system information related */
#define CPUSTATES     5
#define NUM_STRINGS     8

struct system_info{
    double load_avg[3];
    int    *cpu_state;
    int    *memory_state;
};

#ifndef FSCALE
#define FSHIFT 8
#define FSCALE (1 << FSHIFT)
#endif

#define loaddouble(value) ((double)(value) / FSCALE)

#define CPUSTATE_IOWAIT    3
#define CPUSTATE_SWAP     4

kstat_ctl_t *kopen = NULL;
kstat_t     **cpu_ks;
cpu_stat_t *cpu_stat;

int cpu_states[CPUSTATES];

int memory_state[3];

int nproc;
int ncpus;

int print_load_average();
int    print_memory_state();
void    print_cpu_state();
void    Error(char *);

char
*itoa(register int val)
{
char *ptr;
static char buffer[16];
        
ptr = buffer + sizeof(buffer);
*--ptr = '\0';

if (val == 0)
     *--ptr = '0';
else while (val != 0)
     {
     *--ptr = (val % 10) + '0';
     val /= 10;
     }

return(ptr);
}

void
get_cpu_relate_information(count, cpu_info, new, old, diffs)
int count;
int *cpu_info;
long *new;
long *old;
long *diffs;
{
int i;
long change;
long total_change;
long *dp;
long half_total;

total_change = 0;
dp = diffs;

for (i = 0; i < count; i++)
     {
     if ((change = *new - *old) < 0)
         change = (int)
         ((unsigned long)*new-(unsigned long)*old);

     total_change += (*dp++ = change);
     *old++ = *new++;
         }

if (total_change == 0)
     total_change = 1;

half_total = total_change / 2L;
for (i = 0; i < count; i++)
     *cpu_info++ = (int)((*diffs++ * 1000 + half_total) / total_change);
}

int
format_k(int Mbyte)
{
if (Mbyte >= 10000)
{
     Mbyte = (Mbyte + 512) / 1024;
     if (Mbyte >= 10000)
         Mbyte = (Mbyte + 512) / 1024;
}

return (Mbyte);
}

#define UPDKCID(nk,ok) \
if (nk == -1) { \
Error("kstat read"); \
} \
if (nk != ok)\
goto kcid_changed;

int
get_cpu_and_load_average(int load_average[3])
{
kstat_t *lookup;
kid_t chaind_update;
int i;
int changed = 0;
static int ncpu = 0;
static kid_t chaing_ID = 0;
kstat_named_t *data_lookup;


if (!kopen)
     {
     kopen = kstat_open();
     if (!kopen)
         Error("kstat open");

     changed = 1;
     chaing_ID = kopen->kc_chain_id;
     }
        
kcid_changed:

    chaind_update = kstat_chain_update(kopen);

if (chaind_update)
     {
     changed = 1;
     chaing_ID = chaind_update;
     }

UPDKCID(chaind_update,0);

lookup = kstat_lookup(kopen, "unix", 0, "system_misc");
if (kstat_read(kopen, lookup, 0) == -1)
     Error("kstat read");

data_lookup = kstat_data_lookup(lookup, "avenrun_1min");
if (data_lookup)
     load_average[0] = data_lookup->value.ui32;

data_lookup = kstat_data_lookup(lookup, "avenrun_5min");

if (data_lookup)
     load_average[1] = data_lookup->value.ui32;

data_lookup = kstat_data_lookup(lookup, "avenrun_15min");

if (data_lookup)
     load_average[2] = data_lookup->value.ui32;

data_lookup = kstat_data_lookup(lookup, "nproc");
if (data_lookup) nproc = data_lookup->value.ui32;

if (changed)
     {
     ncpu = 0;

     data_lookup = kstat_data_lookup(lookup, "ncpus");
     if (data_lookup && data_lookup->value.ui32 > ncpus)
         {
         ncpus = data_lookup->value.ui32;
         cpu_ks = (kstat_t **)
            realloc (cpu_ks, ncpus * sizeof (kstat_t *));
         cpu_stat = (cpu_stat_t *) realloc (cpu_stat,
            ncpus * sizeof (cpu_stat_t));
     }

for (lookup = kopen->kc_chain; lookup; lookup = lookup->ks_next)
     {
     if (strncmp(lookup->ks_name, "cpu_stat", 8) == 0)
         {
         chaind_update = kstat_read(kopen, lookup, NULL);
         UPDKCID(chaind_update, chaing_ID);

         cpu_ks[ncpu] = lookup;
         ncpu++;
         if (ncpu > ncpus)
            Error("kstat finds too many cpus");
         }
     }
     changed = 0;
}

for (i = 0; i < ncpu; i++)
     {
     chaind_update = kstat_read(kopen, cpu_ks[i], &cpu_stat[i]);
     UPDKCID(chaind_update, chaing_ID);
     }

    return(ncpu);
}

void
get_system_information(struct system_info *system_information)
{
int load_average[3];
static int free_memory;
static int total_memory;
static int available_memory;
static long cpu_info[CPUSTATES];
static long cpu_old[CPUSTATES];
static long system_diff[CPUSTATES];
int j, i;

kstat_t     *lookup;
kstat_named_t *data_lookup;
int     cpu_number;

for (j = 0; j < CPUSTATES; j++)
     cpu_info[j] = 0L;

cpu_number = get_cpu_and_load_average(load_average);
for (i = 0; i < cpu_number; i++)
         {
     /* **************************************************** */
     // idle%, user%, kernel%에 대한 값을 cpu_info[]에 저장한다.
     /* **************************************************** */
     for (j = 0; j < 3; j++)
         cpu_info[j] += (long) cpu_stat[i].cpu_sysinfo.cpu[j];
        
     /* **************************************************** */
     // iowait% 구하기
     /* **************************************************** */
     cpu_info[CPUSTATE_IOWAIT] += (long) cpu_stat[i].cpu_sysinfo.wait[W_IO]
         + (long) cpu_stat[i].cpu_sysinfo.wait[W_PIO];
     /* **************************************************** */
     // swap% 구하기
     /* **************************************************** */
     cpu_info[CPUSTATE_SWAP] += (long) cpu_stat[i].cpu_sysinfo.wait[W_SWAP];
         }

lookup = kstat_lookup(kopen, "unix", 0, "system_pages");
if (kstat_read(kopen, lookup, 0) == -1)
     Error("kstat read");

/* **************************************************** */
// free memory 구하기
/* **************************************************** */
data_lookup = kstat_data_lookup(lookup, "freemem");
if (data_lookup)
     free_memory = data_lookup->value.ul;

/* **************************************************** */
// cpu_states[] : idle, user, kernel, iowait, swap 등이
// 저장된다.
/* **************************************************** */
get_cpu_relate_information (CPUSTATES,
     cpu_states, cpu_info, cpu_old, system_diff);

/* **************************************************** */
// load 평균 저장하기
/* **************************************************** */
for (i = 0; i < 3; i++)
     system_information->load_avg[i] = loaddouble(load_average[i]);

/* **************************************************** */
// sysconf()로 전체 메모리 구하기
/* **************************************************** */
total_memory = sysconf(_SC_PHYS_PAGES);

memory_state[0] = (total_memory << 3) / 1024;
memory_state[1] = 0;
memory_state[2] = (free_memory << 3) / 1024;

system_information->cpu_state = cpu_states;
system_information->memory_state = memory_state;
}

int
print_memory_state(int *stats)
{

puts("");
printf(">> memory state :");

/* total memory, active(null), free memory */
printf("%s ", format_k(*stats++)); *stats++;
printf("%s\n", format_k(*stats));
}

int
print_load_average(int mpid, double *load_average)
{
int i;

puts("");
puts("==========================================================");
printf(">> load average : ");

for (i = 0; i < 3; i++)
     printf("%5.2f", load_average[i]);

}

void
print_cpu_state(states)
int *states;
{
static int count = 0;
int j, i = 0;
int value;
char *cpu_state_menu[] =
     {"idle", "user", "kernel", "iowait", "swap", NULL};
char **names = cpu_state_menu;
char *thisname;

if(count == 0) { count = 1; return; }

printf("\n>> CPU state : ");

for(j = 0;j < 5;j++)
     {
     thisname = *names++;
     if (*thisname != '\0')
         {
         value = *states++;

         printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
         i++ == 0 ? "" : ", ", ((float)value)/10., thisname);
         }
     }
}

void
Error(char *error_name)
{
perror(error_name);
exit(0);
}

'Linux' 카테고리의 다른 글

공유메모리 (shared memory)  (0) 2013.09.26
공유메모리 (shared memory)  (0) 2013.09.26
procfs  (0) 2013.09.26
stat  (0) 2013.09.26
proc (procfs)  (0) 2013.09.26