net-snmp를 통해 시스템 정보 및 실행중인 프로세스의 상태정보 얻어오고자 한다.
간단하게 구현하려고 perl로 만들어 보았으나 cpu를 3~5%나 잡아 먹는다.
2초 간격으로 클라이언트가 정보를 받아가므로 상당한 부하가 예상된다.

net-snmp에 기본적으로 설치되는 ucd-snmp(1.3.6.1.4.1.2021)를 수정해서 사용해야겠다.

우선 각종 시스템 정보 및 프로세스의 상태정보 얻기....
시스템의 cpu사용률 구하는 것은 쉬우나 임의의 프로세스 cpu사용률 구하는건 어렵다.

UCD-SNMP-MIB도 수정했으니 이제 snmpd 소스를 고쳐보자...os별로 언제 다 고쳐..orz ㅜㅜ
일단 리눅스만....>.,<

"수요일에 데모한다는데 언제 할래? 언제 할래? 언제 할래?"


[시스템 상태 및 프로세스별 cpu, mem usage 구하기]

#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define KERNEL_BLOCK_SIZE 512

struct cpudata
{
  unsigned long user, system, idle, nice, total;
};

struct proc_cpudata
{
  unsigned long userproc, systemproc, vmem, rmem;
  char pname[255];
};

struct netdata
{
  unsigned long tx, rx;
};

struct diskdata
{
  unsigned long disk_read, disk_write;
};

/* Get CPU data *//*{{{*/
void get_cpu_stat(struct cpudata *cpu)
{
  FILE *file;
  char temp[10];
  char line[255];

  /* CPU */
  file = fopen("/proc/stat", "r");
  fgets(line, 255, file);
  fclose(file);
  sscanf(line, "%s %lu %lu %lu %lu", temp, &cpu->user, &cpu->nice, &cpu->system,
           &cpu->idle);
  cpu->total = cpu->user + cpu->system + cpu->idle + cpu->nice;

}/*}}}*/

/* Get disk-related information *//*{{{*/
void get_disk_stat(struct diskdata *disk, char *diskname)
{
  FILE *file;
  unsigned long itemp;
  char temp[255];
  char line[255];

  file = fopen("/proc/diskstats", "r");
  if (!file)
  {
       fprintf(stderr, "Error: Disk usage statistics supported for 2.6 kernels only for now.\n");
  }
  else
  {
       while (!feof(file))
       {
           fgets(line, 255, file);
           sscanf(line, "%d %d %s %lu %lu %lu %lu %lu %lu %lu",
                   (int*)&itemp, (int*)&itemp, temp, &itemp, &itemp, &disk->disk_read,
                   &itemp, &itemp, &itemp, &disk->disk_write);
           if (!strncmp(temp, diskname, strlen(diskname)) &&
                   (strlen(temp) == strlen(diskname)))
           {
               break;
           }
       }
       fclose(file);
  }
}/*}}}*/

/* Get process-related information *//*{{{*/
void get_proc_cpu_stat(struct proc_cpudata *proc, int pid)
{
  FILE *file;
  unsigned long itemp;
  char ctemp;
  char line[255];

  sprintf(line, "/proc/%d/stat", pid);
  file = fopen(line, "r");
  if (file == NULL)
  {
       fprintf(stderr, "Error: process (pid %d) not found!\n", pid);
       exit(1);
  }
  fgets(line, 255, file);
  fclose(file);
  sscanf(line, "%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu "
           "%ld %ld %ld %ld %ld %ld %lu %lu %ld",
           (int*)&itemp, proc->pname, &ctemp, (int*)&itemp, (int*)&itemp, (int*)&itemp, (int*)&itemp, (int*)&itemp,
           &itemp, &itemp, &itemp, &itemp, &itemp, &proc->userproc, &proc->systemproc,
           &itemp, &itemp, &itemp, &itemp, &itemp, &itemp, &itemp, &proc->vmem, &proc->rmem
           );

}/*}}}*/

/* Get network stats *//*{{{*/
void get_net_stat(struct netdata *net, char *interface)
{
  FILE *file;
  unsigned long itemp;
  char temp[10];
  char line[255];

  file = fopen("/proc/net/dev", "r");
  fgets(line, 255, file);
  fgets(line, 255, file);
  while (!feof(file))
  {
       int i;
       fgets(line, 255, file);
       strncpy(temp, line, 6);
       sscanf(line + 7, "%lu %lu %lu %lu %lu %lu %lu %lu %lu", &net->rx,
               &itemp, &itemp, &itemp, &itemp, &itemp,
               &itemp, &itemp, &net->tx);
       for (i=0; i < 6; i++)
           if (temp[i] != ' ') break;
       if (!strncmp(temp + i, interface, strlen(interface)))
           break;
       else
           net->rx = net->tx = 0;
  }
  fclose(file);
}/*}}}*/

int childended = 0;

void quit(int nothing)
{
  childended = 1;
}

int main(int argc, char **argv, char **env)
{
  int ch;
  struct cpudata oldcpu, cpu;
  struct proc_cpudata oldproc, proc;
  struct netdata oldnet, net;
  struct diskdata initdisk, olddisk, disk;
  char *progname = strdup(argv[0]);
  unsigned long timer;
  unsigned long disk_in = 0, disk_out = 0;
  unsigned long disk_tx_read = 0, disk_tx_write = 0;
  float maxuload = 0, maxsload = 0, maxpuload = 0, maxsuload = 0, usertime = 0, systemtime = 0;
  int pid;
  unsigned long maxrx = 0, maxtx = 0;
  float time = 0;
  char *interface=NULL, *diskname=NULL;

  signal(SIGCHLD, quit);

  while ((ch = getopt(argc, argv, "i:n:d:v")) != -1)
  {
       switch (ch)
       {
           /* Enable cache */
           case 'i': timer = atoi(optarg); break;
           case 'n': interface = strdup(optarg); break;
           case 'd': diskname = strdup(optarg); break;
           case 'v':
                 printf("System Monitor\n"
                         "Copyright, (C) Eugeni Dodonov, 2004-2005.\n"
                         "Version $Id: monitor.c,v 1.4 2005/09/11 03:15:44 eugeni Exp $.\n"
                         "Distributed under GPL license.\n\n");
                 exit(0);
           default:
                 fprintf(stderr, "Invalid flag %c!\n", (char)optopt);
                 break;
       }

  }
  argc -= optind;
  argv += optind;

  if (argc < 1)
  {
       fprintf(stderr, "Usage: %s [-i interval] [-n net] [-d disk] <pid>|<command>\n", progname);
       exit(1);
  }
  if (timer <= 0)
       timer = 1000000;
  if (!interface)
       interface = strdup("eth0");
  if (!diskname)
       diskname = strdup("hda");
  pid = atoi(argv[0]);

  /* Fork and exec *//*{{{*/
  if (pid <= 0)
  {
       /* Program */
       char *command;
       char **params;
       int i;
       command = strdup(argv[0]);
       params = (char **)malloc((argc) * sizeof(char*));

       for (i=0; i < argc; i++)
       {
           params[i] = (char *)malloc(strlen(argv[i]));
           strncpy(params[i], argv[i], strlen(argv[i]));
       }

       pid = fork();
       if (pid < 0)
       {
           perror("fork");
           exit(1);
       }
       if (pid == 0)
       {
           execve(command, params, env);
           perror("execve");
           exit(1);
       }
  }/*}}}*/

  /* CPU */
  get_cpu_stat(&oldcpu);

  /* DISK */
  get_disk_stat(&olddisk, diskname);
  initdisk = olddisk;
  /* PROC */
  get_proc_cpu_stat(&oldproc, pid);
  /* Network */
  get_net_stat(&oldnet, interface);

  while (!childended)
  {
       unsigned long in, out, maxvmem;
       float uload, sload, procuload, procsload;
       usleep(timer);

       /* CPU */
       get_cpu_stat(&cpu);
       uload = (float) ((cpu.user - oldcpu.user) * 100) / (cpu.total - oldcpu.total);
       sload = (float) ((cpu.system - oldcpu.system) * 100) / (cpu.total - oldcpu.total);
       time += ((float)timer / 1000000);

       /* DISK */
       get_disk_stat(&disk, diskname);
       disk_tx_read = disk.disk_read - olddisk.disk_read;
       disk_tx_write = disk.disk_write - olddisk.disk_write;
       disk_in = disk.disk_read - initdisk.disk_read;
       disk_out = disk.disk_write - initdisk.disk_write;
       olddisk = disk;

       /* PROC */
       get_proc_cpu_stat(&proc, pid);
       usertime = (float)proc.userproc / 100;
       systemtime = (float)proc.systemproc / 100;

       /* Network */
       get_net_stat(&net, interface);
       in = net.rx - oldnet.rx;
       out = net.tx - oldnet.tx;
       oldnet = net;

       /* Format and process acquired data */
       if ((proc.userproc == oldproc.userproc) || (cpu.user == oldcpu.user))
           procuload = 0.0;
       else
       {
           procuload = ((float)(proc.userproc - oldproc.userproc) / (float)(cpu.user - oldcpu.user) * 100);
           procuload *= uload / 100;
       }

       if ((proc.systemproc == oldproc.systemproc) || (cpu.system == oldcpu.system))
           procsload = 0.0;
       else
       {
           procsload = ((float)(proc.systemproc - oldproc.systemproc) / (float)(cpu.system - oldcpu.system) * 100);
           procsload *= sload / 100;
       }

       if (procuload > 100) procuload = 100;
       if (procsload > 100) procsload = 100;
       if (procuload > maxpuload) maxpuload = procuload;
       if (procsload > maxsuload) maxsuload = procsload;
       if (uload > maxuload) maxuload = uload;
       if (sload > maxsload) maxsload = sload;
       if (in > maxrx) maxrx = in;
       if (out > maxtx) maxtx = out;
       if (proc.vmem > maxvmem) maxvmem = proc.vmem;

       oldproc = proc;
       oldcpu = cpu;

       printf("<Stats pname=\"%s\" pid=\"%d\" time=\"%.1f\" usertime=\"%.1f\" "
               "systemtime=\"%.1f\" procuserload=\"%.1f\" maxprocuserload=\"%.1f\" "
               "procsysload=\"%.1f\" masprocsysload=\"%.1f\" userload=\"%.1f\" "
               "maxuserload=\"%.1f\" systemload=\"%.1f\" maxsystemload=\"%.1f\" "
               "vmem=\"%lu\" maxvmem=\"%lu\" rmem=\"%lu\" bytesin=\"%lu\" maxbytesin=\"%lu\" "
               "bytesout=\"%lu\" maxbytesout=\"%lu\" "
               "disk_throughput_read=\"%lu\" disk_throughput_write=\"%lu\" "
               "disk_bytes_read=\"%lu\" disk_bytes_write=\"%lu\" "
               "/>\n",
               proc.pname, pid,
               time, usertime, systemtime, procuload, maxpuload, procsload, maxsuload, uload, maxuload,
               sload, maxsload, proc.vmem, maxvmem, proc.rmem, in, maxrx, out, maxtx,
               disk_tx_read * KERNEL_BLOCK_SIZE, disk_tx_write * KERNEL_BLOCK_SIZE, disk_in * KERNEL_BLOCK_SIZE, disk_out * KERNEL_BLOCK_SIZE);

       fflush(stdout);
  }
  return 0;
}

Posted by 백구씨쥔장
,