앞서 우리는 시그널을 생성하고 시그널을 전달하는 함수에 대해서 배웠다. 이제 시그널을 제어하는 함수를 배워보자.
첫번째 함수는 Sigprocmask이다. 이 함수는 말 그대로 전달되는 Signal에 masking을 진행한다. ( 단, SIGKILL & SIGSTOP의 경우 masking과 handling에서 예외로 작용한다.)
전달되는 매개변수를 하나씩 알아보자.
1. how
how의 값에 따라 sigprocmask의 동작이 달라진다. how에는 아래 세가지 옵션이 존재한다.
SIG_BLOCK : set에 등록된 signal들의 block 설정한다.
SIG_UNBLOCK : set에 등록된 signal들의 block을 해제한다.
SIG_SETMASK : set에 등록된 signal들만 block 하도록 설정하고 나머지의 block은 해제한다.
여기서 의문이다. SIG_BLOCK 과 SIG_SETMASK의 차이는 무엇인가 ?
우선 SIG_BLOCK의 경우 set에 등록된 signal과 함께 set 사용 이전에 block하던 것들도 함께 block 처리한다. 하지만 SIG_SETMASK의 경우 현재 set에 들어있는 signal들만 block 처리하고 이전에 block되어 있던 signal들의 block은 모두 해제한다는 점에서 차이가 있다.
set에 존재하는 모든 signal을 unmask 상태로 초기화한다.
set에 존재하는 모든 signal을 mask 상태로 바꾼다. sigemptyset( )과 반대 !
현재 signal이 전달되었지만 masking처리되어 block된 signal을 확인한다.
signalsuspend의 경우 signal block을 설정함과 동시에 pause를 실행한다.
즉, sigsuspend = sigprocmask + pause가 한번에 작동하는 셈이다.
sleep함수는 특정 시간동안 프로세스를 대기하도록 만든다.
대기한다는 점에서 alarm 함수와 동일하지만 동작방식과 목적 면에서 차이가 있다.
sleep()함수는 주어진 시간동안 프로세스를 대기하도록 만든다. 단! 별도의 signal 은 생성하지 않는다. 반면에 alarm() 함수는 특정시간동안 프로세스를 대기하도록 만들며 SIGALRM이라는 시그널을 생성한다.
추가로 sleep( )함수는 signal handling관련하여 sleep() 함수를 실행하던 중 SIGALRM을 받으면 남은 시간을 나타낼수 있다.
sleep() 함수에는 nanosleep, usleep이 존재한다.
sigsuspend함수를 통해 oldsigset에 block을 걸고 pause 상태로 머무르게한다. 이후 부모 프로세서에서 자식 프로세서 Pid로 SIGUSR1을 보내면 pause단계에 머물러 있던 자식 프로세서가 깨어나며 "child process wakes !! "라는 문장을 출력하고 종료되며 부모 프로세서에 signal을 보내며 프로그램이 종료되게 된다.
그렇다면 여기서 왜 자식 프로세서 sigsuspend함수에 인자로 oldsigset이 들어갔을까?
sigprocmask함수가 실행되며 mysigset 내부에 추가된 SIGUSR1은 마스킹 처리가 되었다. 따라서 child 프로세서 안에서 sigsuspend(&mysigset)을 실행한다면 부모 프로세서에서 넘어오는 SIGUSR1 신호를 block 처리하기 때문에 프로그램이 종료되지않는 현상이 발생하게 된다. 따라서 mysigset이 아닌 oldsigset이 인자로 전달되어야한다.
아무것도 진행되지 않는것을 확인 할 수 있다.
pause 상태로 계속해서 기다리는 것이다.