C++ 시그널 처리 마스터하기: 안전한 인터럽트 관리와 깔끔한 프로그램 종료
시그널이란?
시그널은 운영체제가 프로세스에 전달하는 인터럽트로, 프로그램을 조기에 종료시킬 수 있습니다. UNIX, Linux, macOS, Windows에서 Ctrl+C를 누르면 인터럽트를 생성할 수 있습니다.
잡을 수 있는 시그널 목록
프로그램이 잡을 수 없는 시그널도 있지만, <csignal> 헤더에 정의된 다음 시그널들은 프로그램에서 잡아 적절한 조치를 취할 수 있습니다.
| 번호 |
시그널 및 설명 |
| 1 |
SIGABRT 프로그램의 비정상적 종료, 예: abort() 호출 |
| 2 |
SIGFPE 잘못된 산술 연산, 예: 0으로 나누기 또는 오버플로 |
| 3 |
SIGILL 불법 명령어 감지 |
| 4 |
SIGINT 대화형 주의 시그널 수신 (Ctrl+C) |
| 5 |
SIGSEGV 잘못된 메모리 접근 |
| 6 |
SIGTERM 프로그램에 전송된 종료 요청 |
signal() 함수
C++ 시그널 처리 라이브러리는 예기치 않은 이벤트를 포착하기 위한 signal() 함수를 제공합니다. 구문은 다음과 같습니다.
void (*signal(int sig, void (*func)(int)))(int);
간단히 말해, 이 함수는 두 인자를 받습니다: 첫 번째는 시그널 번호를 나타내는 정수, 두 번째는 시그널 처리 함수에 대한 포인터입니다.
예제: SIGINT 포착하기
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler(int signum) {
cout << "인터럽트 시그널 (" << signum << ") 수신." << endl;
// 정리 및 종료 작업 수행
exit(signum);
}
int main() {
// SIGINT 시그널과 핸들러 등록
signal(SIGINT, signalHandler);
while (true) {
cout << "잠자기 모드 진입..." << endl;
sleep(1);
}
return 0;
}
컴파일 후 실행하면 Going to sleep....이 반복 출력됩니다. 이때 Ctrl+C를 누르면:
Going to sleep....
Going to sleep....
Going to sleep....
인터럽트 시그널 (2) 수신.
raise() 함수
raise() 함수를 사용해 내부적으로 시그널을 발생시킬 수 있습니다. 구문:
int raise(int sig);
sig는 발생시킬 시그널 번호(SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGHUP 등)입니다.
예제: raise()로 시그널 발생시키기
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler(int signum) {
cout << "인터럽트 시그널 (" << signum << ") 수신." << endl;
exit(signum);
}
int main() {
int i = 0;
signal(SIGINT, signalHandler);
while (++i) {
cout << "잠자기 모드 진입..." << endl;
if (i == 3) {
raise(SIGINT); // 3번째 반복에서 SIGINT 발생
}
sleep(1);
}
return 0;
}
실행 결과:
Going to sleep....
Going to sleep....
Going to sleep....
인터럽트 시그널 (2) 수신.