unix에서 시스템 정보를 얻어오는 프로그램을 linux로 포팅하려
글쓴이: nanosec / 작성시간: 수, 2003/05/28 - 12:06오전
아래 코드는 유닉스에서 시스템정보를 얻어오는 프로그램입니다.(한빛에서 나온 유닉스 프로그래밍관련 책 소스입니다.)
리눅스에서 컴파일할경우 시스템관련 구조체나 함수 헤더파일이 없어 컴파일 할 수가 없습니다.
리눅스에서 시스템정보를 얻어오는 함수는 어떤것들이 있나요?
유닉스 프로그램을 리눅스로 포팅한다고 할때는 방법 어떤 방법을 써야 하나요?
많은 가르침 부탁드립니다. ^^
#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);
}Forums:


시스템마다 모두 틀립니다.
위 소스는 솔라리스에서 kstat를 이용하여 리소스를 측정했네요.
TOP를 옮겼군요.
리눅스에서 위와 동일한 정보를 가져오려면, /proc/stat, /proc/loadavg, /proc/meminfo
를 참조하시면 되겠네요
proc에 관한 자세한 정보는 man page를 확인하십시요.
또는 /usr/src/linux/fs/proc 소스를 확인해도 됩니다.
좋은 소득이 있으시길..
브이 V
감사합니다. ^^
감사합니다. ^^
0x2B | ~0x2B
- Hamlet
댓글 달기