Sysinfo(): Difference between revisions

From 탱이의 잡동사니
Jump to navigation Jump to search
(Created page with "== Overview == sysinfo() 함수 내용 설명 == Structure == === Until Linux-2.3.16 === <source lang=c> struct sysinfo { long uptime; /* Seconds since boot *...")
 
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Overview ==
== Overview ==
sysinfo() 함수 내용 설명
sysinfo() 함수 내용 설명.
 
sysinfo()는 시스템 전체 정보를 확인할 수 있는 함수이다. 주변장치를 주 대상으로 하는 sysfs() 와는 달리, sysinfo() 는 커널이 주 대상이다.
 
== Synopsis ==
<source lang=c>
#include <sys/sysinfo.h>
 
int sysinfo(struct sysinfo *info);
</source>


== Structure ==
== Structure ==
Line 46: Line 55:


전체 쓰레드 갯수는 아래의 명령어로 확인할 수 있다.
전체 쓰레드 갯수는 아래의 명령어로 확인할 수 있다.
<pre>
<source lang=bash>
  $ grep -s '^Threads' /proc/[0-9]*/status | awk '{ sum += $2; } END { print sum; }'  
  $ grep -s '^Threads' /proc/[0-9]*/status | awk '{ sum += $2; } END { print sum; }'  
</pre>
</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 */
 
#include <asm/segment.h>
 
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/unistd.h>
#include <linux/types.h>
#include <linux/mm.h>
#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 ==
== Sample ==
Line 81: Line 205:
}
}
</source>
</source>
== See also ==
* http://lxr.free-electrons.com/source/kernel/sys.c#L2293 - sys.c-4.5
* http://lxr.free-electrons.com/source/kernel/info.c?v=2.0.40 - sysinfo()-2.0.40


[[category:c]]
[[category:c]]

Latest revision as of 10:48, 26 April 2016

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