시그널
시그널은 프로세스 간의 비동기적인 메시지 전달 방법으로, 이를 통해 프로세스의 실행 순서를 강제적으로 변경하거나 제어할 수 있다. 이 절의 목표는 시그널의 개념, 사용 방법, 그리고 시그널을 통한 프로세스 제어 방식에 대해 이해한다.
그림으로 배우는 리눅스 구조 정리한 내용
시그널
시그널(Signal)은 소프트웨어 인터럽트로, 특정 이벤트나 예외상황을 비동기적으로 프로세스에 알리기 위함이다. 시그널은 프로세스가 실행 중이거나 대기 상태인지와 관계없이 비동기적으로 발생한다.
시그널을 사용해서 두 프로세스가 서로 시그널을 주고받으며 진행정도를 확인하며 처리를 진행할 수 있다. 다만 시그널은 도착 여부 같은 정보밖에 보낼수 없기 때문에 제약이 많다. 따라서 시그널은 복잡하지 않은 단순한 일을할때만 사용한다.
시그널은 프로세스에 전달되는 이벤트 알림으로, 다음과 같은 다양한 상황에서 사용된다.
1.
프로세스 제어
•
키보드 입력으로 프로세스를 중단하거나 종료 (예:ctrl+C → SIGINT)
•
프로세스 간 통신을 통해 작업 제어가 필요할 때 (예: SIGQUIT로 설정 파일 재로드)
2.
운영 체제 이벤트 처리
•
자식 프로세스 종료 시, 부모 프로세스에 SIGCHLD 시그널 전달
•
메모리 접근 오류 시, SIGSEGV 시그널 발생
3.
사용자 정의 작업
•
사용자가 trap명령 또는 signal시스템 콜로 시그널 핸들러를 설정하여 이벤트를 처리
번호 | 시그널 이름 | 설명 | 발생 조건/용도 |
1 | SIGHUP | 연결 끊김 신호:
터미널 연결 종료 또는 설정 파일 재로드 요청. | 터미널 종료, 설정 파일 재로드 요청, 로그 파일 교체(Logrotate). |
2 | SIGINT | 인터럽트 신호: 프로세스를 중단. | Ctrl+C 입력 또는 사용자 종료 요청. |
9 | SIGKILL | 강제 종료 신호:
즉시 종료, 무시 불가능. | kill -9 <PID>로 강제 종료. |
15 | SIGTERM | 종료 요청 신호:
프로세스 종료 요청. | kill <PID> 명령으로 전달. |
3 | SIGQUIT | 종료 및 디버깅 신호:
프로세스 종료와 함께 메모리 이미지덤프(Core Dump)를 생성 // 덤프 왜뜸?? | Ctrl+\\ 입력으로 발생. |
19 | SIGSTOP | 프로세스 정지 신호:
프로세스를 강제로 중지(무시 불가능). | kill -STOP <PID> 또는 작업 중지 요청. |
18 | SIGCONT | 프로세스 재개 신호:
정지된 프로세스를 다시 실행. | kill -CONT <PID>로 정지된 프로세스를 재개. |
17 | SIGCHLD | 자식 프로세스 종료 알림:
자식 프로세스의 종료/정지 상태를 부모 프로세스에 알림. | 자식 프로세스 종료 또는 상태 변경 시 발생. |
11 | SIGSEGV | 메모리 접근 오류:
유효하지 않은 메모리 접근
(세그멘테이션 오류). | 프로세스가 잘못된 메모리에 접근 |
14 | SIGALRM | 타이머 신호:
설정된 타이머가 만료되었음을 알림. | alarm() 시스템 호출로 설정된 타이머가 만료될 때 발생. |
20 | SIGTSTP | 작업 정지 신호:
터미널에서 입력을 통해 프로세스를 일시 정지. | Ctrl+Z 입력으로 발생. |
시그널 동작 과정
이벤트 발생
-> systemll call 호출
-> 프로세스 PCB에 signal table 신호값 설정(시그널 pending 상태, 대기)
-> 스케줄러 queue 대기
-> 스케줄러 PCB 확인
-> 시그널 핸들러 호출(USER MODE)
-> 수신 상태 확인(receive, block, ignore)
-> 프로세스 실행(Running)
Bash
복사
시그널
•
특정 이벤트나 예외상황을 비동기적으로 프로세스에게 알리기 위함
•
프로세스에 전달되는 이벤트 알림 (s/w 인터럽트)
이벤트 알림
•
키보드입력(예: ctrl+c -> SIGINT시그널, ctrl+z -> SIGSTOP)
•
운영체제 이벤트(예: 메모리 접근 오류 SIGSEGV 시그널)
•
시스템 호출(예:kill() -> SIGKILL)
•
프로세스간 통신(예: 부모프로세스 SIGCHLD)
과정
이벤트 발생 -> systemll call 호출 -> 프로세스 PCB에 signal table 신호값 설정(시그널 pending 상태, 대기) -> 스케줄러 queue 대기 -> 스케줄러 PCB 확인 -> 시그널 핸들러 호출(USER MODE) -> 수신 상태 확인(receive, block, ignore) -> 프로세스 실행(Running)
특징
•
시그널 처리(핸들러 실행)는 반드시 유저 모드에서 수행
•
if 시그널 핸들러가 실행되지 않는 pending 상태에서 다른 시그널 전달되면 무시되어 하나만 남음- 단, sigkill, sigstop은 두 시그널은 수신 상태가 receive, block, ignore에 영향을 받지 않고, 항상 기본 동작만 수행. 핸들러를 설정할 수 없음. 운영체제 기본동작(default action)을 강제 수행따라서 프로세스 종료 시,
•
sigkil 프로세스 즉시종료, 핸들러 설정 불가
•
sigterm 정상 종료(exit) 요청하며, 핸들러를 통해 자원 정리와 같은 추가 작업 가능
사용자 정의 핸들러(Signal Handler)
시그널의 기본 동작을 변경하거나, 특정 작업을 수행하고 싶을 때 사용자 정의 핸들러(Signal Handler)를 설정할 수 있다. 기본 동작대신, 사용자 정의 함수로 동작을 실행하도록 설정 가능하다.
•
시그널 동작:
◦
기본 동작: 종료, 무시, 덤프 생성 등 운영체제에서 정해진 기본동작을 수행
◦
사용자 정의 동작: 시그널 핸들러를 사용하여 특정 작업을 수행
▪
단, SIGKILL과 SIGSTOP은 무시하거나 처리기로 처리할 수 없다.
시그널은 프로세스가 실행 중이거나 대기 상태인지와 관계없이 비동기적으로 발생합니다. 시그널은 커널 모드에서 유저 모드로 복귀하는 시점에 처리됩니다.
트랩(Trap)
쉘 스크립트에서 trap 명령을 사용하여 특정 시그널을 처리
trap 'echo "SIGINT received"; exit' INT
Bash
복사
SIGKILL vs SIGTERM
SIGTERM
•
SIGTERM은 프로세스가 종료 요청을 처리하도록 기회를 주며, 파일 저장, 리소스 해제, 로그 기록 등의 정리 작업을 수행할 수 있습니다.
•
프로세스가 정상적으로 종료할 수 있는 경우, 항상 SIGTERM을 우선 사용해야 한다.
•
프로세스가 시그널을 처리할 수 있으므로 종료 요청을 무시하거나, 특정 종료 로직을 실행하도록 프로그래밍할 수 있다.
SIGKILL
•
프로세스를 강제로 종료하므로 정리 작업이 수행되지 않는다.
•
강제 종료로 인해 데이터 손실 및 시스템 불안정이 발생할 수 있다.
•
프로세스가 SIGTERM을 무시하거나, 응답하지 않는 상태인 경우에만 사용해야 한다.
•
SIGKILL은 캡처 불가능하며, 프로세스가 반드시 종료된다.
•
하지만 드물게 uninterruptible sleep 상태의 프로세스는 SIGKILL 시그널을 무시할 수 있다. 이러한 프로세스는 ps 명령어의 STAT 필드에서 D로 표시된다. 이 상태는 주로 I/O 작업 대기나 커널 관련 작업 중 발생한다.
SIGHUP(Signal Hangup)
번호 | 시그널 이름 | 발생 및 용도 |
1 | SIGHUP / HUP | 터미널 연결 끊김 알림 → 시스템 관리와 애플리케이션 운영 목적으로 확장 |
•
초기 목적으로 사용자가 터미널 세션에서 로그아웃하거나 연결이 끊어졌을 때, 터미널에서 실행중이던 프로세스 종료를 알리기 위해 사용되었다. 프로세스가 백그라운드로 실행 중이어도 터미널과 연결이 끊기면 기본적으로 종료한다.
•
프로세스 재로드(reload) 요청: 설정 파일을 다시 읽거나, 실행 중인 프로세스를 종료하지 않고 새로운 설정을 갱신하기 위해 사용된다. 서버나 데몬(daemon)에서 활용한다.
•
서비스 유지: 서비스를 중단하지 않고 환경 설정을 업데이트 하거나 상태를 초기화 하기 위해 사용된다.
사용 사례
1.
서버 및 데몬에서의 재로드
설정 파일을 변경한 후 프로세스를 재시작하지 않고 반영하기 위해 SIGHUP 신호를 보낸다.
// 이게 어찌하여 프로세스를 죽이지 않고, 재시작하지 않고 반영이 된다는거지??
kill -SIGHUP <PID>
kill -SIGHUP $(cat /var/run/nginx.pid) <- 설정파일인가??
Python
복사
2.
터미널 세션 관리
사용자가 로그아웃하거나 SSH 세션이 종료 되어도, nohup 을 통해서 프로세스가 계속 실행하도록 관리한다. 표준 출력과 표준에러를 script.log에 저장하여 로그를 통해서 실행상태를 확인 가능하다.
nohup <command> &
nohup python sctipt.py &
nohup python script.py > script.log 2>&1 &
Python
복사
•
nohup: 시그널을 무시하도록 프로세스를 실행하는 유틸리티.
•
2>&1: 표준 에러 출력(파일 디스크립터 2)을 표준 출력(파일 디스크립터 1)으로 연결
기존에 백그라운드에서 실행 중인 프로세스를 nohup없이 시작했더라도, disown을 사용하면 SIGHUP의 영향을 받지 않도록 설정할 수 있다.
# 기존에 실행한 백그라운드 프로세스
python script.py &
# `jobs` 명령으로 백그라운드 프로세스 확인
jobs
# 특정 작업을 `disown` (예: 첫 번째 작업)
disown %1
Bash
복사
•
disown은 현재 셸에서만 유효하다. 따라서 셸이 종료되기 전에 사용해야 한다.
•
disown을 사용한 프로세스는 해당 세션에서 더 이상 jobs 명령으로 확인할 수 없다.
nohup이나 disown으로 SIGHUP 시그널을 무시하도록 설정된 프로세스를 종료하려면, 강제 종료를 위한 SIGKILL 시그널을 사용
실습: SIGINT 무시 프로그램
다음은 SIGINT 시그널을 무시하도록 설정한 예제 프로그램이다.
•
intignore.py
#!/usr/bin/python3
import signal
# SIGINT 시그널 무시
signal.signal(signal.SIGINT, signal.SIG_IGN)
while True:
pass
Python
복사
# 프로세스 종료
$ ps
PID TTY TIME CMD
12345 pts/1 0:00 ./intignore.py
$ kill -9 12345
Shell
복사
•
Ctrl+C를 눌러도 프로그램이 종료되지 않는다.
•
Ctrl+Z
•
프로그램 종료를 위해서는 kill 명령어를 사용해야 한다.
마무리
시그널은 프로세스의 실행 흐름을 제어하고 프로세스 간 통신을 지원하는 강력한 메커니즘이다. 적절한 시그널 처리 및 핸들러 설정은 시스템 안정성과 효율성을 높이는 데 중요하다.
Q&A
Related Posts
Search