Signal이란 말 그대로 어떠한 이벤트가 발생하여 전송하는 ‘신호’이다. Signaling은 마찬가지로 어떠한 신호를 보내는 것을 의미한다.
예를 들어, 프로세스 진행 중에 ‘Ctrl + c’를 눌러 본 적이 있을 것이다. 이 때 프로세스는 신호를 받고 프로세스를 종료한다. 프로세스에게 kill 명령을 내리는 것도 마찬가지이다. 따라서 Signaling은 소프트웨어 인터럽트 역할을 하여 프로세스에 무엇인가 발생하였음(이벤트)을 알리는 메시지를 전송하게 된다.
Signal을 받은 프로세스는 Signal에 따라 지정된 기본 동작(default action: killing terminal)을 수행할 수도 있고, 사용자가 사전 정의해 놓은 함수(Signal handler)를 실행할 수 있다.
‘kill -l’ 명령어를 통해 지원하는 Signal의 종류를 확인할 수 있다. 아래의 그림 2는 각각의 기능에 대한 간단한 설명이다.
그림 1) 지원하는 Signal 종류
그림 2) Signal에 대한 설명
리눅스 환경에서 Signal을 사용하여 프로세스 간의 통신을 하기 위한 헤더 파일이 있다. Signal은 <signal.h> 라는 헤더 파일에 정의되어 있다. 이 헤더 파일을 불러오면 리눅스 환경에서 Signaling을 구현할 수 있다.
아래의 코드는 Signaling을 구현하여 'Keyboard Interupt (Ctrl + c)' 신호를 받으면 실행 중인 프로세스를 강제적으로 종료하도록 작동한다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // for Linux Compiling (GCC)
#include <signal.h> // for Signals
void handlerFunction(int sig) { // Handler Function
printf("\n>>> Received Keyboard Interupt(Ctrl+c) Signal!\n");
printf(">>> Program will be terminated, if one more Keyboard Interupt Signal!!!\n");
// SIGINT: Signal Terminal Interupt
// SIG_DFL: Default Action for Signal (kill terminal if received SIGINT again)
signal(SIGINT, SIG_DFL);
}
int main() {
// Execute 'handlerFunction()' if received SIGINT(Keyboard Interupt: 'Ctrl + c')
signal(SIGINT, handlerFunction);
int cnt = 0;
while(1) {
printf("Time: %d(sec)\n", cnt++);
sleep(1);
}
printf("Program Terminating...\n");
exit(0);
}
위의 소스 코드를 gcc로 컴파일하고 실행하게 되면 Time을 측정하고 키보드 인터럽트(Ctrl+c)가 발생할 경우 알림을 한 번 준다. 이후 한 번 키보드 더 인터럽트 신호가 발생하면 즉시 종료된다.
그림 3 Signaling 예제 코드 실행 화면