본문 바로가기
Linux

[Linux] Linux의 Signal을 알아보자 (1)

by Meanings_ 2025. 1. 17.

Signal

✅ 개요

  • 프로세스 또는 시스템에게 이벤트 발생을 전달하는 신호를 말함.
  • 많은 부분이 비동기이지만 일부는 동기적임.
    • 동기 : 이벤트가 있어야 발생, 비동기 : 예측불가
    • 예) 사용자가 누르는것 (ctrl+c와 같이)
  • divide zero는 인터럽트일수도 있고 시그널일수도 있음.

🤿 정리

시그널의 발생은 두가지로 나뉨. -> 비동기(예측불가), 동기(예측가능)
시그널의 처리는 오로지 비동기임.

😫 왜 쓸까?

  • 특정 이벤트가 발생했음을 알려주는 알림메세지의 기능을 하기 위해 쓴다.
  • 예를 들어 프로세스가 무한루프를 돌고 있는데 이걸 꺼야한다. → 그때 sigint를 보내서 강제 종료를 시켜버린다.
  • 특정 프로세스를 강제종료 시키고 싶다 → 터미널에 sigkill -9 {프로세스 이름}을 명령어로 입력해 강제 종료 시켜버린다.

📍 Signal이 동적인 상황은?

  • 프로세스가 프로세스에게 시그널을 보내거나 사용자가 시그널을 보내는 경우.
  • 이벤트는 비동기적으로 발생할 수 있으며 시그널을 전달받은 프로그램은 시그널을 시그널 핸들러를 통해 비동기적으로 처리할 수 있음.
    ✅ 중단된 프로세스의 상태는 누가, 어떻게 관리할까?
  • 커널이 관리함. 프로그램 카운터, 레지스터 값, 스택 포인터 값을 관리하고 있다가 나중에 시그널 발생으로 인해 중단된 지점에서 재개

📍 리눅스의 주요 시그널

이름 설명
SIGALRM alram()으로 설정한 타이머가 만료되었을때 발생.
SIGBUS 하드웨어 고장에 해당하는 시그널.
SIGCHILD 프로세스가 종료 또는 중단되면 부모에게 이 시그널 전달. 기본적으로 무시되기 때문에 자식의 상태가 변할 때 마다 그 사실을 알아야 한다면 부모는 반드시 이 시그널을 캐치해야함.
SIGINT 사용자가 DELETE 또는 Ctrl+C를 눌렀을때 터미널 드라이버가 이 시그널 발생.
SIGKILL 무시하거나 캐치 불가. sigkill -9 {프로세스 번호} 이면 강적조합.
SIGSTOP 무시하거나 캐치할 수 없는 두 시그널 중 하나로 프로세스 중단
SIGTSTP 사용자가 터미널에서 Ctrl+Z(일시정지 키) 를 눌렀을때 터미널 드라이버가 이 시그널 발생
SIGUSR1, SIGUSR2 사용자 정의 시그널

📍 커널의 시그널 처리 방식

  1. 시그널 무시
    1. 어떤 액션도 취하지 않는다.
  2. 디폴트 액션 실행
    1. 사용자 지정 핸들러
    2. 대부분 프로세스 종료
  3. 시그널 캐치하여 실행
    1. 함수를 새로 만든다.
    2. 커널은 프로세스의 현재 코드의 실행을 중단하고 이전에 등록했던 시그널 처리함수로 넘어가서 그 코드를 실행.
    3. 시그널 처리함수가 리턴되면 시그널이 발생하기 전 위치로 돌아감

📍 Signal(2)

#include <signal.h>
sighandler_t signal(int signum , sighandler_t handler);
  • signum 자리에는 시그널의 이름을 쓴다
  • handler 인자에는 시그널 발생시 호출될 함수의 주소를 넣는다.

📍 task_struct

  • 아래는 리눅스의 task_struct의 예시.
    • 프로세스를 나타내는 자료구조이다.

image

  • pending은 bit별로 시그널을 구분한다.
  • handler는 시그널의 불려지면 디폴트로 호출된다.
  • blocked는 masked와 같은 의미로 프로세스와 관련된 block은 전부 mask시킨다.

✅ PCB와 task_struct의 관계

  • 운영체제를 배우면 PCB라는 말을 익히 듣는다.
  • 리눅스에서 PCB를 task_struct라는 친구가 대체하고 있는것이다
    image
    • task_struct안에 시그널 핸들러도 들어간다!

🧩 인터럽트와 시그널의 차이?

  • 이쯤이면 궁금해질것이다. 인터럽트와 시그널의 차이가 무엇인지!
  • 간단히 말하면 인터럽트는 바로 실행할 수 있지만, 시그널은 프로세스에게 보내는 것이기에 바로 실행되지 못한다!
    • 후술하겠지만 시그널은 Signal은 pending이 될 수 있다. 딴일하느라 안볼 수도 있다.

인터럽트

  • 인터럽트 크게 하드웨어 인터럽트와 소프트웨어 인터럽트로 나뉜다.
  • 하드웨어 인터럽트
    • 외부 디바이스에서 발생
    • CPU가 현재 실행중인 작업 멈추고 → 인터럽트 핸들러 실행
  • 소프트웨어 인터럽트
    • 동기적 : 시스템콜
    • 비동기적 : trap
      • divide in zero
      • page fault

시그널

  • os나 프로세스가 특정 프로세스에게 보내는 비동기적 이벤트
  • 프로세스가 실행중일 때만 처리

🤝Recap
인터럽트는 CPU와 커널 중심, 시그널은 실행중인 프로세스 중심

📍 kill(2)

#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);
  • pid에게 signal을 보낸다
  • kill()은 프로세스 그룹에 시그널 보내는 시스템콜 함수
  • % kill -9 1093 ⇒ 1093번 프로세스에게 SIGKILL을 보낸다
  • % kill 1093 ⇒ 1093번 프로세스에게 SIGTERM을 보낸다 (무시,catch가능)

'Linux' 카테고리의 다른 글

[Linux] Linux의 Signal을 알아보자(2)  (0) 2025.01.17