Signal이란?

  • 의미를 전달하는 방법으로 시그널과 메세지는 조금의 차이를 지닌다.
  • 시그널은 하나의 의미만을 지니고 있으며 간단하고 빠른 전달을 위해 사용된다.
  • 하지만 복잡한 내용 전달에는 사용되지 않는다.

Signal in OS

인간과 OS 사이에는 응용프로그램이 존재한다. 물론 메세지로 데이터 통신을 할 수도 있겠지만 굳이 이렇게 복잡한 통신이 필요하지 않다면 이런 통신은 불필요하다고 볼 수 있다. 때문에 OS는 여러 Signal을 지원하여 단순한 통신을 가능하게 하였다.

예제1. SIGINT Handler

키보드 입력으로 발생시킬 수 있는 시그널은 여러 종류가 있다.

  • Ctrl+C : SIGINT (프로세스를 종료시킨다.)
  • Ctrl+Z : SIGSTP (프로세스를 중단시킨다.)
  • Ctrl+\ : SIGQUIT (core dump를 남기고 프로세스를 종료시킨다.)

이 중에 SIGINT라는 신호를 handling하는 함수를 한번 실행 시켜보자.

signal1.c

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


void handler(int sig){
  //SIGINT라는 신호가 오면 유저한테 물어본다. 
  if (sig == SIGINT) {
    printf("Do you want to quit?") ;
    if (getchar() == 'y')
    exit(0) ;
  }
}

int main(){
  signal(SIGINT, handler) ;
  while(1) ;
}

결과는 아래와 같이 Ctrl+C가 실행되면 핸들러가 일하게 된다.

jeongjinhyeog-ui-MacBook-Pro:IPC jeongjinhyeog$ ./signal1
^CDo you want to quit?y

예제2. SIGTERM 활용 프로그램 죽이기

유저가 언제 프로그램을 죽일지 모르기 때문에 시그널을 보내 이벤트로 처리하는 것이 좋다.

SIGTERM은 프로그램을 종료하기 전에 프로그램을 종료하는 처리를 수행한다.

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


void handler(int sig){
  printf("Do you want to quit?") ;
  if (getchar() == 'y')
  exit(0) ;
}

int main(){
  int d ;
  //TERM은 SIGINT와 다르다.
  //Exit을 코드로 짜는 것보다 유저가 언제든 끌 수 있게 시그널로 하는 것이 좋다.
  //두개의 프로그램 사이에 시그널으로 통신할 수 있다.
  //엄청난 정보는 아니더라도 간단하게 서로에게 신호를 줄 수 있다. (시그널 자체로는 데이터를 주고 받을 수는 없다.)
  signal(SIGTERM, handler) ;
  scanf("%d", &d) ;
}

이 프로그램을 실행하면 signal을 기다리게 된다.

jeongjinhyeog-ui-MacBook-Pro:IPC jeongjinhyeog$ ./signal2

ps를 이용해서 해당 프로세스의 id를 찾고 죽여보자.

jeongjinhyeog-ui-MacBook-Pro:Programmers jeongjinhyeog$ ps
  PID TTY           TIME CMD
70415 ttys000    0:00.11 -bash
70427 ttys001    0:00.51 -bash
36680 ttys002    0:00.19 -bash
39987 ttys002    0:00.00 ./signal2
40021 ttys003    0:00.03 -bash
jeongjinhyeog-ui-MacBook-Pro:Programmers jeongjinhyeog$ kill 39987

그 후 해당 프로세스를 실행중인 terminal을 확인해보면 핸들러가 실행된 것을 볼 수 있다.

jeongjinhyeog-ui-MacBook-Pro:IPC jeongjinhyeog$ ./signal2
Do you want to quit?

예제 3. SIGALRM 활용 알람 보내기

SIGALRM은 알람을 보내주는데 활용되는 시그널이다.

  • t라는 itimerval 변수를 생성하고 시간 주기를 설정해주고
  • setitimer를 사용하면 핸들러로 원하는 시간을 보내줄 수 있다.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>

void
handler(int sig)
{
printf("Ring\n") ;
}

int main(){
  struct itimerval t ;
  //알람 타이머
  signal(SIGALRM, handler) ;
  //시간의 양을 정한다
  t.it_value.tv_sec = 1 ;
  t.it_value.tv_usec = 100000 ; // 1.1 sec
  //interval을 주면 시간 간격마다 링하게 된다.
  t.it_interval = t.it_value ;
  
  //시간을 설정하는 함수로 일정 시간이 되면 시그널을 보내게 할 수 있다.
  setitimer(ITIMER_REAL, &t, 0x0) ;
  while (1) ;
}

실행 시 일정한 간격을 두고 계속해서 Ring이 울리는 것을 볼 수 있다.

jeongjinhyeog-ui-MacBook-Pro:IPC jeongjinhyeog$ ./signal3
Ring
Ring
Ring
Ring
Ring
Ring

느낀점

일단 많은 양의 복잡한 내용을 보내는 데는 사용할 수 없겠지만 빠른 단순한 통신에는 매우 용이할 것 같다!