예외처리 #3 [CSAPP Chap 8]

지금까지 다룬 예외들은 저수준 메커니즘이었다. 시그널은 보다 높은 수준의 소프트웨어 ECF이다. 운영체제는 시근러을 통해 프로세스에게 “이런 이벤트 발생”이라고 열러준다. 예를 들어 사용자가 쉘에서 Ctrl+C 를 누르면 운영체제는 현재 실행 중인 프로세스에게 “종료”라는 의미의 시그널을 보낸다.


2025.10.20 - [컴퓨터 이론/CS:APP] - 예외처리 #2 [CSAPP Chap 8]

 

예외처리 #2 [CSAPP Chap 8]

앞서 논한 예외는 운영체제가 하드웨어를 제어하는 저수준 메커니즘이었다. 이제부터는 이 메커니즘을 활용해서 운영체제가 수행하는 일들을 확인 해 볼 수 있다. 프로세스와 동시성CPU 코어는

hyeonistic.tistory.com

 

시그널의 종류와 역할

시그널은 리눅스 시스템에서 약 30여 종이 있으며, 각각 정해진 의미가 있고 고유한 번호와 이름도 있다. 가장 흔한 시그널들을 보면 :

SIGINT : Signal Interrupt

  • 프로세스 중단 지시
  • Ctrl+C 에서 보통 쉘이 현재 실행중인 프로그램에게 보낸다.

SIGKILL

  • 프로세스 즉시 종료
  • kill -9 <PID> 와 같은 명령어로 사용자가 직접 보낼 때 사용한다. 이 시그널은 프로세스가 무시하거나 잡을 수 없다.

SIGSEGV : Signal Segmentation Violation

  • 프로세스가 허용되지 않은 메모리 영역에 접근했다는 심각한 오류를 말하는데, Seg Fault 가 이것이다.
  • 커널이 프로세스의 잘못된 메모리 접근을 감지 한 경우 해당 프로세스에게 보낸다.

시그널을 보내는 주체는 크게 두 가지 경로가 있다.

  1. 커널 : 하드웨어 예외(0으로 나누기, 잘못된 메모리 접근)이 발생하거나 Ctrl+C 를 누르는 경우이다.
  2. 다른 프로세스 : kill 명령어를 입력한 경우.

SIGKILL 는 다른 시그널과 비교 했을 때 회피가 불가능한데, SIGINT 등의 시그널은 사전에 다르게 처리하게끔 시그널 핸들러를 설정 해줄 수 있다. 하지만 SIGKILL 은 해당이 없다.

 

 

시그널 보내기와 받기

대부분의 시그널에 대해 프로세스는 다음 세 가지 중 하나의 행동을 취할 수 있다.

  1. 기본 행동 수행 : 각 시그널마다 정해진 기본 동작을 따른다.
  2. 무시 : 시그널을 무시하고 아무런 동작도 하지 않는다.
  3. 처리 : 시그널을 잡아 미리 등록해둔 특별한 함수인 시그널 핸들러를 실행한다.

시그널 처리 방식을 등록하기 위해서는 signal() 또는 더 정교한 제어가 가능한 sigaction() 이라는 시스템 콜을 사용한다. 프로그램은 이 시스템 콜을 통해 자신이 실행 할 함수를 전달 할 수 있다.

시그널 핸들러를 처리하는 와중에 사용자가 Ctrl+C 를 한번 더 누르는 경우, 기존 처리가 끝날 때까지 어딘가에 잠시 대기 후 실행이 이루어진다. 일단 블록 후, pending 상태로 대기 큐에 등록되어 기존 핸들러의 종료를 기다린다.

 

 

시그널과 프로세스 그룹

cat report.txt | grep "error" | wc -l 과 같은 파이프라인 명령을 실행하면 실제로는 3개의 프로세스가 구분되어 실행되지만, Ctrl+C 를 누르면 동시에 종료가 이루어진다.

이는 프로세스 그룹이라는 개념을 사용하기 때문이다. 앞에서 언급한 명령어의 실행으로 쉘은 다음 단계를 따른다.

  1. cat, grep , wc 세 개의 자식 프로세스를 생성한다.
  2. 이 세 프로세스를 하나의 새로운 프로세스 그룹으로 묶는다.
  3. 이 프로세스 그룹을 터미널의 전경 작업으로 설정한다.

사용자가 터미널에서 Ctrl+C 를 누르면, 터미널 드라이버는 현재 실행 중인 단일 프로세스에게 SIGINT 를 보내는 것이 아니다. 대신, 터미널에 연결된 전경 프로세스 그룹에 속한 모든 프로세스에게 SIGINT 시그널을 보낸다. 따라서 cat , grep , wc 세 프로세스가 모두 동시에 SIGINT 를 받고 함께 종료되는 것이다.

이 메커니즘 덕분에 사용자는 파이프라인으로 엮인 여러 프로세스를 하나의 작업처럼 제어 할 수 있다.