Signals

Update:     Updated:

Category:

Tags:


큰 용량의 데이터를 다운 받는 등 오래 걸리는 작업을 할 때 주로 background 프로세스로 실행한다. 하지만 프로세스가 끝날 때까지 기다리지 않기 때문에 자원을 회수하지 못하고 좀비 프로세스가 되기 쉽다. 만약 프로세스가 끝났을 때 signal을 보내고, 신호를 받고 자원을 바로 회수한다면 이를 간편하게 해결할 수 있다.


Signals

어떤 예외적인 상황이 발생했다는 것을 알려주는 일종의 메시지

커널에서 프로세스로 정보를 주고 전송하며, 각 signal에 따른 signal handler를 수행한다. 유닉스에서는 기본적으로 30개 정도의 시그널 이벤트를 미리 정의하고 있다.

ex. signal in LINUX

2 SIGINT terminate ctrl + c
6 SIGABRT dump abort function call
8 SIGFPE dump arithmetic exception
9 SIGKILL terminate cannot override !
11 SIGSEGV terminate segmentation fault
14 SIGALRM terminate timer and send signal
17 SIGCHLD ignore child terminated/stopped
19 SIGSTOP stop ctrl + z


ex. ctrl+c 랑 ctrl + z 두 가지 다 foreground 프로세스들을 종료/중단시키는 역할을 한다.

image


Sending Signal : kill(2), raise(3)

kill 함수는 특정 프로세스에게 신호를 보내고, raise는 자기 자신에게 신호를 보낸다.

int kill(pid_t pid, int signo);
int raise(int signo);

// return 0, -1 on errpor
  • pid > 0 : pid인 프로세스에게 신호 전달
  • pid == 0 : 호출한 프로세스와 같은 그룹에 속한 모든 프로세스에게 전달
  • pid == -1 :
    • euid == 0 : 호출한 프로세스를 제외한 모든 프로세스에 전달
    • euid != 0 : 프로세스를 호출한 유저가 실행하는 모든 프로세스에 전달
  • pid < -1 : -pid인 프로세스와 같은 그룹인 모든 프로세스에 전달


Sending Signal : alarm(2), pause(2)

alarm 함수는 지정한 시간이 지나면 SIGALRM 시그널을 보내는 함수이고, pause는 다음 시그널을 받을 때까지 일시정지 시키는 함수이다.

unsigned int alarm(unsigned int seconds);
// returns 0 or remaining seconds of previous alarm 

int pause(void);
//returns -1 with errno set to EINTR



Pending/Blocking Signal

신호를 받았지만 그에 대한 action을 취하지 않은 상태를 pending 되었다고 한다. 신호 종류 하나당 하나의 pending만 가능하기 때문에, 같은 종류의 신호가 들어오면 버려진다.

그리고 신호를 아예 받지 않는 상태를 blocking이라고 한다. 신호가 전달될 수는 있지만, blocking이 해제될 때까지 시그널은 무시된다.

커널의 Process Context Block(PCB)에는 다음과 같이 pending과 blocking 정보를 저장하는 비트가 포함되어 있다.

image

신호가 처음 전달되면, pending 벡터에 해당 시그널 인덱스의 값을 1로 변환한다. 그리고 block 벡터의 값을 확인해서 1인 경우에는 신호를 버리고, 0인 경우 action을 취해도 된다고 판단한다.


Receiving Signal

신호를 수신(receive)한다는 것은 신호를 전달 받고 그에 대한 action까지 취한다는 것을 말한다. 수신하는 방법에는 다음과 같이 여러가지가 있다.

  • Ignore : 아무것도 하지 않는 경우
  • Stop(Suspend) : SIGCONT 신호에 의해 다시 시작될 때까지 중단
  • Terminate : 받은 즉시 종료
  • Core Dump : 메모리에 이전 정보를 저장한 후 종료
  • Catch : 등록한 signal handler를 통해 수행


Signal이 receive되는 시점

신호는 context switch가 발생하고 그 뒤에 다음 프로세스가 다시 실행되는 시점에 수신(receive)된다. 이 시점에서 커널은 signal이 전달된게 있는지 확인하고, 있는 경우 그에 대한 signal handler를 수행한다.

image


Signal이 receive되는 과정

pnb(pending non-block) = pending & ~blocked

커널은 먼저 pending bit이 1인지를 확인하고, 그 후 block bit를 확인해서 0인 경우 pnb에 1을 저장한다. 그래서 pnb = 0인 경우에는 신호를 무시하고 다음 프로세스를 수행하고, pnb = 1인 경우에는 신호를 수신하고 그에 대한 action을 취한다.



@Advanced Programming in the UNIX environment, Third edition 내용을 참고함

맨 위로 이동하기