리눅스 프로그래밍 - 프로세스 종료 신호(SIGINT, SIGTERM) 후킹하기

반응형

 

리눅스 프로그래밍 - 프로세스 종료 신호(SIGINT, SIGTERM) 후킹하기

본 글에서는 리눅스 어플리케이션 프로세스의 종료 신호를 후킹하여 원하는 동작을 수행하도록 하는 방법에 대해 소개한다.

 

보통 루프를 도는 어플리케이션 프로세스의 경우 Ctrl + C를 입력하여 프로세스를 종료하거나(foreground에서 동작하는 경우), kill 명령을 이용하여 프로세스를 종료한다(background에서 동작하는 경우).

 

Ctrl + C를 입력하거나 kill 명령을 이용하여 프로세스를 종료하고자 할 때, 프로세스가 종료되기 전에 특정 동작을 수행할 필요가 있는 경우가 있다. (예: 시스템에 생성해 놓은 공용 자원 해제, 다른 프로세스와의 정보 교환, 디바이스 드라이버의 상태 변경 등)

이 경우, Ctrl + C 입력 신호나 kill 명령에 의한 신호를 후킹하여 원하는 동작을 수행하도록 할 수 있다.

 

Ctrl + C 입력 시, 프로세스에는 SIGINT라는 신호가 전달된다.

kill 명령을 통한 프로세스 종료 시, 프로세스에는 SIGTERM이라는 신호가 전달된다.

 

일반적인 프로세스는 이 두 신호를 수신하면 시스템에 정의된 기본 종료 절차에 의해 종료된다.

하지만, 프로세스 상에서 이 두 신호를 처리하는 핸들러를 등록하게 되면, 두 신호를 수신할 경우 해당 핸들러가 호출되게 된다. 따라서 해당 핸들러 안에 프로세스 종료 시점에 수행되기를 원하는 동작을 구현할 수 있다.

 

특정 신호를 후킹하여 처리하는 핸들러를 등록하기 위해서 signal() 함수를 사용한다.

 

다음은 SIGINT 및 SIGTERM 신호를 후킹하여 원하는 종료 코드를 수행하는 예제 코드이다.

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


/**
 * @brief 신호를 처리하는 핸들러
 * @param[in] signo 신호 번호
 */
static void signal_handler(int signo)
{
  if (signo == SIGINT) {
    // do something
  }
  else if (signo == SIGTERM) {
    // do something
  }

  // do something

  exit(0);
}


/**
 * @brief 샘플 프로그램 메인 함수
 */
int main(int argc, char *argv[])
{
  printf("Start sample program\n");

  /*
   * SIGINT, SIGTERM 신호에 대한 핸들러를 등록한다.
   */
  if (signal(SIGINT, signal_handler) == SIG_ERR) {
    printf("Fail to signal(SIGINT): %m\n");
    return -1;
  }
  if (signal(SIGTERM, signal_handler) == SIG_ERR) {
    printf("Fail to signal(SIGTERM): %m\n");
    return -1;
  }

  /*
   * do something
   */
 

  /*
   * 무한루프를 돈다.
   *   - Ctrl + C 입력 또는 kill 명령으로 종료해야 한다.
   */
  while(1) {
    // do something
  }

  return 0;
}

 

본 글에서는 SIGINT와 SIGTERM 신호에 대한 예제를 보였지만, 그 외 신호에 대해서도 핸들러 등록 및 처리가 가능하다.

 

댓글

Designed by JB FACTORY