Note/Memo2010. 10. 20. 16:53


 
 그전에 포스팅한 내용은 /proc/stat과 /proc/meminfo 를 이용하여 CPU 사용률 과 메모리 사용률을 구하였다.

이번에는 sysinfo() 함수를 이용하여 proc 파일 시스템을 만들어본다.
(본 내용은 짧은 영어 실력으로 번역하여 이해한 것으로 틀린 부분이 있으면 지적 부탁드립니다)

 sysinfo 함수는 유저 영역에서 동작하는 함수로 proc 파일 시스템으로 동작하기 위해서는 부적합하다고 보인다.
하지만 proc 파일 시스템으로 만들면 좀 더 있어 보인다(?)는 이유로 강행하게 되었다.

sysinfo의 설명을 살펴보면 다음과 같다.
 

NAME

sysinfo - returns information on overall system statistics 

SYNOPSIS

#include <sys/sysinfo.h>

int sysinfo(struct sysinfo *info); 

DESCRIPTION

Until Linux 2.3.16,sysinfoused to return information in the following structure:


struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
char _f[22]; /* Pads structure to 64 bytes */
};
이하 생략..

loads[3]을 살펴보면 1분, 5분 15분간 평균적인 load를 나타낸다고 되어 있다. 이 수치는 /proc/stat과 다르게 평균적으로 로딩되어진 프로세스들의 갯수를 뜻한다.  그리고 하나의 단점은 멀티코어 프로세서에는 normalize 되지 않았다고 한다. load average 가 1 인경우에는 싱글프로세서 인경우 CPU사용률 100% 인것이고, 쿼드 코어인경우에는 25% 이라고 한다.(자세한것은 man 쳐보세요~)

어째든 이러한 정보를 토대로 코딩을 한 내용이다( 주석으로 설명을 대신하겠습니다)
 1 #include <linux/init.h>
  2 #include <linux/kernel.h>
  3 #include <linux/proc_fs.h>
  4 #include <asm/uaccess.h>
  5
  6 typedef struct sysinfo sysInfo_t;
  7 struct proc_dir_entry *sysinfo_entry;
  8
  9 static int read_sysinfo(char *page, char **start, off_t off,
 10         int count, int *eof, void *data)  // cat /proc/sysinfo 라고 쳤을때 실행되는 함수(proc 파일 시스템 read 함수)
 11 {      
 12     int len;
 13     unsigned int cpuUsage, memUsage;
 14     sysInfo_t getSysInfo;
 15     mm_segment_t old_fs = get_fs(); // 지금 현재영역 데이터 세그먼트 영역 저장
 16     set_fs(KERNEL_DS); //커널 데이터 세그먼트로 변경
 17     sys_sysinfo(&getSysInfo); // sysinfo 함수 호출(해당 함수는 시스템 영역에서 호출된는 함수 - User영역은 sysinfo())
 18     set_fs(old_fs);
 19     cpuUsage = (getSysInfo.loads[0]*100)/(60*HZ); //CPU 사용율을 구한다.
 20     memUsage = ((getSysInfo.totalram - getSysInfo.freeram)*100) / getSysInfo.totalram; //메모리 사용률을 구한다
 21
 22     len = sprintf(page, " CPU Usage : %d %% \n Memory Usage : %d %%\n", cpuU    sage, memUsage); // 화면에 출력
 23
 24   if (len <= off+count)
 25       *eof = 1;
 26   *start = page + off;
 27   len -= off;
 28   if (len > count)
 29       len = count;
 30   if (len < 0)
 31       len = 0;
 32
 33   return len;
 34
 35 }
 36
 37
 38
 39 int __init sysinfo_probe(void) // 모듈 시작 뿐
 40 {
 41
 42     sysinfo_entry = create_proc_read_entry("sysinfo", 0644, NULL, read_sysinfo, NULL); //proc 파일 시스템을 만든다
 43     if(sysinfo_entry)
 44          printk(KERN_INFO "Proc entry for driv successfully created");
 45
 46
 47      return 0;
 48 }
 49
 50 static void __exit sysinfo_exit(void) // 모듈 종료 함수(해당 모듈을 unload 시)
 51 {
 52     // Remove the /proc entry
 53     remove_proc_entry("sysinfo", NULL);
 54
 55     return;
 56 }
 57 module_init(sysinfo_probe);
 58 module_exit(sysinfo_exit);


 어떻게 보면 너무 간단하다..
Posted by 스카이데이즈


Note/Memo2010. 10. 15. 11:50



해당 값을 구하기 위하여 /proc/meminfo 와 /proc/stat을 활용하였다.

먼저현재 CPU 사용률을 구해야하는데 리눅스는 이것을 /proc/stat에 텍스트 형태로 저장한다.
각 필드는 리눅스 시간 단위인 jiffies로 내용은 아래와 같다.

- user: normal processes executing in user mode
- nice: niced processes executing in user mode
- system: processes executing in kernel mode
- idle: twiddling thumbs
- iowait: waiting for I/O to complete
- irq: servicing interrupts
- softirq: servicing softirqs
- steal: involuntary wait


jiffies 는  리눅스 커널에서의 동작 시간을 나타내는 전역 변수이다. HZ값에 알맞게 세팅된 타이머
인터럽트가 주기적으로 발생하면 커널은 시스템 기준 시간을 유지하기 위해서 jiffies라는 변수값을
타이머 인터럽트가 뜰 때마다 1씩 증가 시킨다.

리눅스에서 man 5 proc 이라고 치면 다음과 같은 내용을 알 수 있다

 /proc/stat
              kernel/system statistics.  Varies with architecture.  Common entries include:

              cpu  3357 0 4313 1362393
                     The amount of time, measured in units of USER_HZ (1/100ths of a second on most archi-
                     tectures),  that  the  system spent in user mode, user mode with low priority (nice),
                     system mode, and the idle task, respectively.  The last value should be USER_HZ times
                     the second entry in the uptime pseudo-file.

                     In  Linux  2.6 this line includes three additional columns: iowait - time waiting for
                     I/O to complete (since 2.5.41); irq - time servicing interrupts (since  2.6.0-test4);
                     softirq - time servicing softirqs (since 2.6.0-test4).

                     Since Linux 2.6.11, there is an eighth column, steal - stolen time, which is the time
                     spent in other operating systems when running in a virtualized environment

              page 5741 1808
                     The number of pages the system paged in and the number  that  were  paged  out  (from
                     disk).

              swap 1 0
                     The number of swap pages that have been brought in and out.

              intr 1462898
                     This line shows counts of interrupts serviced since boot time, for each of the possi-
                     ble system interrupts.  The first column is the total  of  all  interrupts  serviced;
                     each subsequent column is the total for a particular interrupt.

              disk_io: (2,0):(31,30,5764,1,2) (3,0):...
                     (major,minor):(noinfo, read_io_ops, blks_read, write_io_ops, blks_written)
                     (Linux 2.4 only)

              ctxt 115315
                     The number of context switches that the system underwent.

              btime 769041601
                     boot time, in seconds since the Epoch (January 1, 1970).
              processes 86031
                     Number of forks since boot.

              procs_running 6
                     Number of processes in runnable state.  (Linux 2.5.45 onwards.)

              procs_blocked 2
                     Number of processes blocked waiting for I/O to complete.  (Linux 2.5.45 onwards.)


위 글을 보면  Jiffes는 HZ 값에 따라 1분에 카운터 되는수치가 다르다는 것을 알 수 있다. 근데보통 100이라고하는데확인할필요성이있다. kerenl_source_dir/arch/Architecture_Type/param.h에보면 HZ값이디파인값이확인되어있으니확인해보자

필자가 사용하는 보드인 경우에는 100으로 설정되어 있어 소스코드 또한 그에 맞게 코딩하였다. 만약 HZ가 200이면 0.005초 간격으로 Jiffies값이 1식 증가한다.

그리고 보드에서 사용할 수 있도록 busybox에 추가하였다. busybox 추가를 위한 수정은 diff_log를 참조하길 바란다.

cpuRate 함수를 보면 리턴을 다음 과 같이 한다.

  58     double result =(double)(CpuAfterStat.user + CpuAfterStat.nice + CpuAfterStat.system) - (double)(CpuBeforeStat.user + CpuBeforeStat.nice + CpuBeforeStat.system);
 59
 60     return (result / ((afterTime-beforeTime)*100))*100;

 측정 시간을 1초로 한경우에는 result 자체가 CPU 사용률이 된다. 이유 인 즉슨, 1초에 jiffes는 총 100개 증가하며 그중 User/Nice/System에 사용된 jiffes는 N/100 이다. 따라서 백분률로 따지면 N 그 자체가 되는 것이다.

 (afterTime-beforeTime)*100) 으로 한 것은 1초에 jiffes가 100증가해서 이다. HZ가 200이면 200을 넣어줘야할 것이다. 그 뒤에 100은 백분률을 위한 100 - _



Posted by 스카이데이즈