[시스템프로그래밍] - 시그널(Signal)

2019. 11. 20. 03:01Computer Science/SystemProgramming

컴퓨터 시스템 내부에서 시그널(Signal)어떤 이벤트가 시스템에 발생했다는 것을 프로세스에게 알려주는 짧은 메세지이다.

  • 예외상황과 인터럽트를 커널에서 추상화한 개념
  • 프로세스와 프로세스간에 통신의 방법
  • 서로 다른 시그널들은 정수 아이디로 구분한다.
  • 프로세스는 특정 시그널을 제외한 통상적인 시그널들에 대해 무시할 수 있다.

시그널의 송신

  • 커널은 목적지 프로세스의 일부 상태를 갱신하는 방법으로 목적지 프로세스에 전송함
  • 커널은 다음과 같은 경우에 시그널을 보낸다.
    • 0으로 나누기나 자식 프로세스의 종료 같은 시스템 이벤트를 감지 했을 때
    • 다른 프로세스로부터 kill 시스템 콜 요청을 받았을 때

시그널의 수신

목적지 프로세스가 시그널을 받을때, 어떤 형태로든 반응을 하도록 커널에 의해 요구될 때, 시그널을 받는다고 한다.

세가지 반응

  • 무시: Ignore the signal - do nothing
  • 대상 프로세스를 종료
  • 시그널 핸들러 라고 부르는 유저레벨 함수를 실행하여 시그널을 잡는다(catch)
    • 비동기형 인터럽트에 대한 응답으로 호출되는 인터럽트 핸들러 방식과 유사
    • p.s 비동기형인터럽트 발생시 cpu는 인터럽트 핀을 세팅(하드웨어레벨임)해서 인터럽트 핸들러를 실행 한 후 인터럽트 직전 명령어 다음 명령어로 복귀한다.   
    •  
  • 전송하였지만, 아직 수신되지 않은 시그널은 pending(대기하고 있다)고 한다.
    • 어느 특정 타입의 시그널에 대해서 최대 한 개의 대기 시그널이 존재할수 있다.
    • ** 시그널은 큐에 들어가지 않는다.
      • 프로세스가 이미 k타입의 시그널을 가지고 있다면, 다음에 오는 k타입의 시그널들은 무시된다.
  • 프로세스는 특정 시그널의 수신을 블록(거절) 할 수 있다.
    • 프로세스에서 블록될 수 없는 유일한 시그널은 SIGKILL이다.
    • 블록된 시그널들은 전달될 수 있지만, 시그널이 풀릴 때까지는 수신될 수 없다.
    • pending - 대기 시그널들을 표시 
      • 커널은 타입 k 시그널이 도착할 때마다 pending 값의 k번째 비트를 1로 설정
      • 커널은 타입 k 시그널을 수신할 때마다 pending 값의 k번째 비트를 0으로 설정
    • blocked - 블록된 시그널들을 표시
      • 시그널 프로세스 마스크를 이용하여 응용 프로그램이 1 또는 0으로 설정 - 설정된 마스크로 들어오는 시그널을 필터해서 받을건지 말건지 정해서 죽임
  • 대기하는 시그널은 최대 한번만 수신할 수 있다.

컴퓨터 시스템 내부에서 발생되는 예외는 크게 두가지 종류가 있다.

  • 비동기형 :  ctrl-del-alt나 ctrl-c, 본체 리셋 버튼 등 사용자의 갑작스러운 입력이나 예측할 수없는 상황을 가르킨다.
  • 동기형 : traps,falts,aborts로 나뉘는데 이들의 공통점은 명령어를 실행한 결과로 발생된다

ctrl-c 와 ctrl-z

  • ctrl-c:SIGINT(인터럽트 시그널)인데, 이것은 포 그라운드로 실행중인 모든 프로세스를 '종료' 시킨다.
  • ctrl-z:SIGSTP(스탑 시그널)인데, 이것은 포 그라운드로 실행중인 모든 프로세스를 '중단' 시킨다.
  • STAT
    • S: sleeping
    • T:stopped
    • R:running

fork로 만들어진 자식프로세스에 대해 ctrl-z 요청으로 생성된 자식프로세스들에 대해 중단된 상태를 보여주는 것이다. 반대로 아래의 상황은 fork로 인해 생성된 자식프로세스에 대해 ctrl-c 요청을 받고, 그 요청에 의해 종료되어 shell에 의해 회수당해서 시스템 내에 존재하지 않는 상황을 보여준다.

 

Kill을 사용해서 프로세스를 죽이는 예제

fork로 자식 프로세스를 생성하고 while(1)로 무한루프를 돌린다.(N의 갯수 만큼 만듬)

  • N의 횟수 만큼, 특정 pid에 대해 kill 시그널로 인터럽트 명령을 보낸다.
  • N의 횟수 만큼, 부모 프로세스가 자식의 종료를 wait를 기다리게 하고 종료 후에, 정상 종료를 확인하고, 정상 종료일 경우 어떤 자식 프로세스가 종료되었는지 표시한다.
  • 정상 종료가 아닐경우 abort된 경우이므로, abort 메세지를 출력한다.

rf.

WIFEXITED(status) : 자식이 정상적으로 종료되었다면 non-zero 이다.

WEXITSTATUS(status) : exit()를 호출하기 위한 인자나 return 값이 설정되고 종료된 자식의 반환 코드의 최하위 8비트를 평가한다. 이 매크로는 정상정료 - WIFEXITED(status) - 일때만 평가된다.

 

 

이처럼 시그널은 시스템 내부에서 프로세스와 커널간의 통신에 쓰이는 통신 단위이다.