'fork'에 해당되는 글 1건

  1. 2007/01/17 간단 프로세스 모니터

간단 프로세스 모니터

프로그래밍/서버프로그래밍 2007/01/17 15:08

리눅스머신에서 프로세스 모니터 by xevious7

프로세스 모니터는 여러가지 방법으로 구현될 수 있습니다.
제가 쓰는 방법을 공개해보겠습니다.

일단 플랫폼은 Linux 플랫폼입니다.

방법론은 fork 와 exec 를 이용하여 프로그램구동후에
kill 을 이용하여 프로세스를 검사 프로세스가 죽었으면
다시 가동시키는 형태 입니다.

알고리즘과 의사코드

  1. 실행할 프로세스에 대한 정의를 한다.
   2. 프로그램실행 함수
          2-1  fork를 이용하면 현재 프로세스를 복사한다.
          2-2  child프로세스인지 검사
                     child 프로세스이면  exec 로 원하는 프로그램을 실행시킨다.

  3 무한루프
                   kill(child_process_id , 0 ) 를 콜한다.
                   kill 이 실패하면  프로세스는 응답없음 이므로  (프로그램실행 함수를 콜)
                   성공이라면 루프계속

간단한설명

       fork : fork시스템콜은 유닉스계열 머신에서 프로세스 자신을 복사하는 명령이다.
               fork를 콜한 시점이후부터 같은 프로세스가 존재하게 된다.
               fork의 리턴값은 fork를 수행한 패런트(부모) 프로세스는 차일드 프로세스아디가
               되고 차일드 프로세스에서는 0가 된다.

       exec : 현재의 프로세스가 다른 프로그램을 실행시키는 명령으로 이것을 수행하면
                현재의 프로세스가 실행하고자 하는 프로그램으로 변경된다.
       kill : 프로세스를 검사하거나 프로세스를 죽인다.
              옵션에 0 를 사용하면 프로세스를 검사하게 된다.

소스코드.
//
// Utility module.
// PMON.CPP
// Author : EuiBeom Hwang 1994- 2004. 2006.
//          1994 Created.
//
// Process Monitor Module.
// Process Start and Monitoring. Recovering.
//
//

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

char g_sExeFile[200];
char g_sExePath[200];
int  g_nChildPid;

void init0()
{
 

  memset(g_sExeFile,0,200);
  memset(g_sExePath,0,200);

  strcpy(g_sExePath,"... 프로그램 Path ");
  strcpy(g_sExeFile,"... 프로그램명");


}

void starter()
{

  g_nChildPid = fork(); // fork process
  if(g_nChildPid < 0) {
    printf("[START][FORK] process fork fails");
    printf("[SHUTDOWN] Monitor closed.");
     exit(0);
  }

  if(g_nChildPid == 0)  // if child
  {
        if(execl(g_sExePath,g_sExeFile,(char *) 0) < 0)
        {
           printf("[EXEC] process execution fails");
           exit(0);
        }
  }
  printf("[START] %s process started. pid=%d",g_sExeFile,g_nChildPid);

}


int main(int argc,char *argv[])
{
int nChildPid;
long ctime,otime;

  init0(); // default setup.
  signal(SIGCLD,SIG_IGN);
 
 
  starter();

  ctime = otime = time(NULL);

  while(1)
  {
    ctime = time(NULL);
    if((ctime - otime) > 30) { // 30 초 + 알파 마다 확인. 이 알파값은 kill명령과
                                       // otime = ctime; 대입 명령의 실행시간임
        if( kill(g_nChildPid,0) < 0) {
           printf("[MON] process stopped. %d",g_nChildPid);
           starter(); // restart.
        }
        else printf("[MON] process is healthy %d",g_nChildPid);

       otime = ctime;
    }
    sleep(1);  // 슬립이 없으면 무한루프문으로 인해 cpu점유율이 높아진다.
  } // while end.

}

PS 원 코드는 이것보다 잡다한 여러가지 루틴과 연결되어 있지만 간단 설명을
위해서 코드를 수정하였습니다.

잡다한 루틴이라는 것은 init 부분에서 외부 ini 파일로 부터 설정값을 가져오는
부분등의 파일처리, 각각의 결과를 로그파일로 저장하는 부분등의 파일처리 등입니다.

핵심 부분은 아니지만
실제응용에서는 꼭 필요한 부분들의 코드입니다. 하지만 그 부분들은
각각의 응용에 따라 달라지고 설명하고자 하는 부분과 거리가 멀기 때문에
삭제하였습니다.

PS. :
http://www.linuxjunkies.org/html/Process-Monitor-HOWTO.html 
위 사람의 프로세스모니터도 같은 형태군요. fork - exec - kill 을 통한 확인입니다.
이분은 sleep를 정밀하게 하기위해서 리눅스프로그래머들이 많이 쓰는
select를 이용한 시간체크를 했네요. 또한 옵션이나 부가적인 것까지
된 범용으로 만들어놓았습니다.
바로 이용을 위해서라면 저 URL에서 파일복사후 컴파일하셔서
문서에 나온 사용법대로 사용하시면 되겠습니다.

top