Sysinfo()
Overview
sysinfo() 함수 내용 설명. sysinfo() 는 커널이 주 대상이다. 주변장치를 주 대상으로 하는 sysfs() 와는 차이가 난다.
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 으로 확인된 프로세스 갯수가 서로 맞지 않는 것을 확인할 수 있다. 쓰레드 갯수로 확인하면 갯수가 맞는 것을 확인할 수 있다.
전체 쓰레드 갯수는 아래의 명령어로 확인할 수 있다.
$ grep -s '^Threads' /proc/[0-9]*/status | awk '{ sum += $2; } END { print sum; }'
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
<source lang=c>
- include <stdio.h>
- 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
- 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