Sysinfo()

From 탱이의 잡동사니
Jump to navigation Jump to search

Overview

sysinfo() 함수 내용 설명.

sysinfo()는 시스템 전체 정보를 확인할 수 있는 함수이다. 주변장치를 주 대상으로 하는 sysfs() 와는 달리, sysinfo() 는 커널이 주 대상이다.

Synopsis

<source lang=c>

  1. include <sys/sysinfo.h>

int sysinfo(struct sysinfo *info); </source>

Structure

Until Linux-2.3.16

<source lang=c> 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 */

}; </source>

Since Linux-2.3.23

<source lang=c> 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 */
   unsigned long totalhigh; /* Total high memory size */
   unsigned long freehigh;  /* Available high memory size */
   unsigned int mem_unit;   /* Memory unit size in bytes */
   char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */

}; </source>

Process count

sysinfo() 함수를 이용하면 현재 프로세스의 갯수 정보를 확인할 수 있다. <source lang=c> unsigned short procs; /* Number of current processes */ </source> 얼핏보면 단순한 프로세스의 갯수 정보일 것 같지만, 사실은 프로세스가 아니라 쓰레드 갯수로 표현해야 함이 맞다. 실제로 프로그램을 작성해서 돌려보면 sysinfo() 로 확인된 프로세스의 갯수와 ps/top 으로 확인된 프로세스 갯수가 서로 맞지 않는 것을 확인할 수 있다. 쓰레드 갯수로 확인하면 갯수가 맞는 것을 확인할 수 있다.

전체 쓰레드 갯수는 아래의 명령어로 확인할 수 있다. <source lang=bash>

$ grep -s '^Threads' /proc/[0-9]*/status | awk '{ sum += $2; } END { print sum; }' 

</source>

Implement

왜 sysinfo() 의 procs 가 쓰레드 갯수를 나타내는지는 sysinfo() 를 어떻게 구현했는지를 살펴보면 된다. 간단하게 procs가 nr_threads 를 참조하기 때문이다. <source lang=c> /**

* do_sysinfo - fill in sysinfo struct
* @info: pointer to buffer to fill
*/

static int do_sysinfo(struct sysinfo *info) {

   unsigned long mem_total, sav_total;
   unsigned int mem_unit, bitcount;
   struct timespec tp;
   memset(info, 0, sizeof(struct sysinfo));
   get_monotonic_boottime(&tp);
   info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0);
   get_avenrun(info->loads, 0, SI_LOAD_SHIFT - FSHIFT);
   info->procs = nr_threads;
   si_meminfo(info);
   si_swapinfo(info);
   /*
       * If the sum of all the available memory (i.e. ram + swap)
       * is less than can be stored in a 32 bit unsigned long then
       * we can be binary compatible with 2.2.x kernels.  If not,
       * well, in that case 2.2.x was broken anyways...
       *
       *  -Erik Andersen <andersee@debian.org>
       */
   mem_total = info->totalram + info->totalswap;
   if (mem_total < info->totalram || mem_total < info->totalswap)
           goto out;
   bitcount = 0;
   mem_unit = info->mem_unit;
   while (mem_unit > 1) {
       bitcount++;
       mem_unit >>= 1;
       sav_total = mem_total;
       mem_total <<= 1;
       if (mem_total < sav_total)
           goto out;
   }
   /*
       * If mem_total did not overflow, multiply all memory values by
       * info->mem_unit and set it to 1.  This leaves things compatible
       * with 2.2.x, and also retains compatibility with earlier 2.4.x
       * kernels...
       */
   info->mem_unit = 1;
   info->totalram <<= bitcount;
   info->freeram <<= bitcount;
   info->sharedram <<= bitcount;
   info->bufferram <<= bitcount;
   info->totalswap <<= bitcount;
   info->freeswap <<= bitcount;
   info->totalhigh <<= bitcount;
   info->freehigh <<= bitcount;

out:

   return 0;

} </source>

구 버전(아마도 2.3.16 버전 이전)의 경우는 nr_tasks 를 참조한다. <source lang=c> /*

* linux/kernel/info.c
*
* Copyright (C) 1992 Darren Senn
*/

/* This implements the sysinfo() system call */

  1. include <asm/segment.h>
  1. include <linux/sched.h>
  2. include <linux/string.h>
  3. include <linux/unistd.h>
  4. include <linux/types.h>
  5. include <linux/mm.h>
  6. include <linux/swap.h>

asmlinkage int sys_sysinfo(struct sysinfo *info) {

   int error;
   struct sysinfo val;
   error = verify_area(VERIFY_WRITE, info, sizeof(struct sysinfo));
   if (error)
       return error;
   memset((char *)&val, 0, sizeof(struct sysinfo));
   val.uptime = jiffies / HZ;
   val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
   val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
   val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
   val.procs = nr_tasks-1;
   si_meminfo(&val);
   si_swapinfo(&val);
   memcpy_tofs(info, &val, sizeof(struct sysinfo));
   return 0;

} </source>

Sample

<source lang=c>

  1. include <stdio.h>
  2. include <sys/sysinfo.h>

int main(int argc, char** argv) {

   struct sysinfo info;
   
   sysinfo(&info);
   
   printf("uptime[%ld]\n",     info.uptime);
   printf("load_1[%lu]\n",     info.loads[0]);
   printf("load_5[%lu]\n",     info.loads[1]);
   printf("load_15[%lu]\n",    info.loads[2]);
   printf("total ram[%lu]\n",  info.totalram);
   printf("free ram[%lu]\n",   info.freeram);
   printf("shared ram[%lu]\n", info.sharedram);
   printf("buffer ram[%lu]\n", info.bufferram);
   printf("total swap[%lu]\n", info.totalswap);
   printf("free swap[%lu]\n",  info.freeswap);
   printf("procs[%d]\n",       info.procs);
   printf("total high[%lu]\n", info.totalhigh);
   printf("free high[%lu]\n",  info.freehigh);
   printf("free high[%lu]\n",  info.freehigh);
   printf("mem unit[%u]\n",   info.mem_unit);
   
   return 0;

} </source>

See also