unix에서 시스템 정보를 얻어오는 프로그램을 linux로 포팅하려

nanosec의 이미지

아래 코드는 유닉스에서 시스템정보를 얻어오는 프로그램입니다.(한빛에서 나온 유닉스 프로그래밍관련 책 소스입니다.)

리눅스에서 컴파일할경우 시스템관련 구조체나 함수 헤더파일이 없어 컴파일 할 수가 없습니다.

리눅스에서 시스템정보를 얻어오는 함수는 어떤것들이 있나요?

유닉스 프로그램을 리눅스로 포팅한다고 할때는 방법 어떤 방법을 써야 하나요?

많은 가르침 부탁드립니다. ^^

#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);
}
yaang_kr의 이미지

위 소스는 솔라리스에서 kstat를 이용하여 리소스를 측정했네요.
TOP를 옮겼군요.

리눅스에서 위와 동일한 정보를 가져오려면, /proc/stat, /proc/loadavg, /proc/meminfo
를 참조하시면 되겠네요

proc에 관한 자세한 정보는 man page를 확인하십시요.
또는 /usr/src/linux/fs/proc 소스를 확인해도 됩니다.

좋은 소득이 있으시길..

브이 V

nanosec의 이미지

감사합니다. ^^

0x2B | ~0x2B
- Hamlet

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.