사용자 프로세스는 시그널을 이용하여 비동기적인 긴급 이벤트를 인터럽트 처리처럼 다룰 수 있다.
사용자 관점
커널 관점
시그널 전달
프로세스에 시그널이 전달되었을 때 ➡︎ PCB의 보류 시그널 테이블에 표시(mark)
전달된 시그널은 언제 처리되는가?
➡︎ 프로세스가 실행 상태가 될 때 (커널의 컨텍스트 스위치로), 결국 사용자 모드로 진입할 때
사용자 모드로 돌아가기 직전에, 시그널 핸들러가 실행됨
아직 처리되지 않은 시그널
➡︎ pending signal (보류 중인 시그널)
사용자에 의해 시그널 처리를 일시적으로 차단할 수 있음
➡︎ signal blocking(시그널 블로킹)
(시그널 처리 흐름)
1) instruction m 실행 중 시그널이 발생함
2) 커널이 프로세스를 대신해서 시그널 핸들러 호출
3) 시그널 핸들러 코드 실행
4) 핸들러가 종료되면 → 인터럽트된 위치 (instruction m+1)로 복귀
SIG_DFL (기본 시그널 핸들러 사용)
보통 에러가 발생했을 때 시그널이 발생함
핸들러는 커널이 제공함
기본 동작은 종료 또는 코어덤프 후 종료
SIG_IGN (시그널 무시)
프로세스가 자체적으로 핸들러를 등록함
ex: ^C (kill) → 기본은 종료
→ 사용자가 정의하면 ^C로 게임 종료 등 다른 행동 가능




✔️시그널 번호는 시스템마다 다를 수 있으니 숫자 대신 이름(SIGABRT 등)을 사용하는 것이 좋다.
#include <signal.h>
typedef void (*sighandler_t)(int); // void 함수 포인터
sighandler_t signal(int signum, sighandler_t handler);
(매개변수)
(반환값)
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
(매개변수)
(반환값)
성공 시 0
실패 시 -1

#include <signal.h>
int raise(int sig);
(매개변수)
(반환값)

#include <unistd.h>
unsigned alarm(unsigned sec);
(매개변수)
(반환값)
이전 알람이 있었던 경우: 그 알람까지 남은 시간(초)
처음 호출한 경우: 0
(주의)‼️
리눅스는 한 번에 하나의 알람만 허용
새 알람이 이전 알람을 대체함
alarm(0)은 이전 알람 취소

#include <stdlib.h>
void abort(void);

#include <unistd.h>
int pause(void);
(반환값)
기본 시그널 핸들러가 사용된 경우 ➡︎ 프로세스 종료 (pause 함수로 복귀하지 않음)
사용자 정의 시그널 핸들러가 사용된 경우 ➡︎ 핸들러 실행 후 pause()에서 복귀