시스템프로그래밍_ 11-Signal & Timer

안수빈·2025년 6월 14일

시스템프로그래밍

목록 보기
6/7
post-thumbnail

<Signal (시그널)>

사용자 프로세스는 시그널을 이용하여 비동기적인 긴급 이벤트를 인터럽트 처리처럼 다룰 수 있다.

사용자 관점

  • 사용자 모드 실행 중 → 시그널 발생 → 사용자 프로그램이 인터럽트됨 →
    시그널 핸들러(인터럽트 핸들링처럼 사용자 모드에서 실행) → 종료 또는 인터럽트된 지점으로 복귀

커널 관점

  • 이벤트 발생 (예: 세그먼트 오류) → 해당 프로세스의 PCB 시그널 테이블에 시그널(SIGSEGV 등)을 표시 → 사용자 모드로 복귀 직전에 → 시그널 핸들러로 제어가 이동 (스택 수정) → 종료 또는 사용자 모드로 복귀 → 인터럽트 핸들링과는 달리 약간의 지연이 있을 수 있음

시그널 전달

  • 커널 ➡︎ 사용자, 사용자 ➡︎ 사용자

<Signal Handling (시그널 처리)>

  • 프로세스에 시그널이 전달되었을 때 ➡︎ PCB의 보류 시그널 테이블에 표시(mark)

  • 전달된 시그널은 언제 처리되는가?

    ➡︎ 프로세스가 실행 상태가 될 때 (커널의 컨텍스트 스위치로), 결국 사용자 모드로 진입할 때

    사용자 모드로 돌아가기 직전에, 시그널 핸들러가 실행됨

  • 아직 처리되지 않은 시그널
    ➡︎ pending signal (보류 중인 시그널)

  • 사용자에 의해 시그널 처리를 일시적으로 차단할 수 있음
    ➡︎ signal blocking(시그널 블로킹)



(시그널 처리 흐름)
1) instruction m 실행 중 시그널이 발생함

2) 커널이 프로세스를 대신해서 시그널 핸들러 호출

3) 시그널 핸들러 코드 실행

4) 핸들러가 종료되면 → 인터럽트된 위치 (instruction m+1)로 복귀


<Three Ways of Signal Handling (시그널 처리의 세 가지 방식)>

SIG_DFL (기본 시그널 핸들러 사용)

  • 보통 에러가 발생했을 때 시그널이 발생함

  • 핸들러는 커널이 제공함

  • 기본 동작은 종료 또는 코어덤프 후 종료

SIG_IGN (시그널 무시)

  • 단, SIGKILL, SIGSTOP은 무시 불가

사용자 정의 시그널 핸들러 사용

  • 프로세스가 자체적으로 핸들러를 등록함

    ex: ^C (kill) → 기본은 종료
    → 사용자가 정의하면 ^C로 게임 종료 등 다른 행동 가능






✔️시그널 번호는 시스템마다 다를 수 있으니 숫자 대신 이름(SIGABRT 등)을 사용하는 것이 좋다.


<signal(2) 함수>

#include <signal.h>

typedef void (*sighandler_t)(int);  // void 함수 포인터
sighandler_t signal(int signum, sighandler_t handler);
  • 사용자 정의 시그널 핸들러 설정

(매개변수)

  • signum: 시그널 번호
  • handler: 사용자 정의 시그널 핸들러 함수 (signum 시그널에 대해)

(반환값)

  • 성공 시 ➡︎ 이전 시그널 핸들러의 주소
    실패 시 ➡︎ SIG_ERR

  • 시그널 핸들러는 기본적으로 한 번만 사용됨
    - 첫 시그널 수신 후 SIG_DFL로 리셋됨
    - 일부 OS는 핸들러를 계속 유지함

<시그널 보내기>- kill()

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

int kill(pid_t pid, int sig);

(매개변수)

  • pid: 프로세스 ID
  • sig: 시그널 번호

(반환값)

  • 성공 시 0
    실패 시 -1


<자기 자신에게 시그널 보내기>- raise()

#include <signal.h>
int raise(int sig);

(매개변수)

  • sig: 시그널 번호

(반환값)

  • 성공 시 0
    실패 시 -1


<알람 설정>- alarm()

#include <unistd.h>

unsigned alarm(unsigned sec);

(매개변수)

  • sec: 초 단위로 SIGALRM 시그널을 자기 자신에게 보냄

(반환값)

  • 이전 알람이 있었던 경우: 그 알람까지 남은 시간(초)

  • 처음 호출한 경우: 0

(주의)‼️

  • 리눅스는 한 번에 하나의 알람만 허용

  • 새 알람이 이전 알람을 대체함

  • alarm(0)은 이전 알람 취소


<abort() 함수>

#include <stdlib.h>

void abort(void);
  • 비정상적인 프로세스 종료 유도
    SIGABRT 시그널을 생성 → 코어 덤프 후 종료


<pause() 함수>

#include <unistd.h>

int pause(void);
  • 어떤 시그널이 도착할 때까지 대기함

(반환값)

  • 기본 시그널 핸들러가 사용된 경우 ➡︎ 프로세스 종료 (pause 함수로 복귀하지 않음)

  • 사용자 정의 시그널 핸들러가 사용된 경우 ➡︎ 핸들러 실행 후 pause()에서 복귀

0개의 댓글