시그널에 대한 더 많은 정보를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.
https://reakwon.tistory.com/233
시그널에 대해서 이야기하는 3번째 시간이 되겠네요. 지난 번에는 시그널 개념과 시그널 관련함수까지 다루어 봤습니다.
시그널 개념과 시그널 핸들러와 시그널 관련 함수(sigfillset, sigemptyset, sigaddset, sigdelset, sigprocmask)는 지난 번 포스팅을 참고하시기 바랍니다.
이번에는 시그널에 대한 sigpending과 sigismember에 대해서 알아보도록 하겠습니다.
- sigpending
int sigpending(sigset_t *set);
현재 블록되어 대기중인 signal들을 set에 담게 됩니다. 만일 블록될 signal들이 {SIGINT, SIGTSTP} 라고 하고 SIGTSTP가 블록된 상태라면 set에는 {SIGTSTP}가 들어가게 되지요. 이 함수가 성공했다면 0, 실패했다면 -1을 반환합니다.
- sigisempty
int sigismember(sigset_t *set, int signo);
현재 set에 signo(시그널 번호)가 포함되어 있는지 알아냅니다. 만약 set에 해당하는 시그널 번호가 존재한다면 1, 없다면 0을 반환하게 됩니다. -1을 반환할때도 있는데 이 경우는 시그널을 확인할 수 없다는 의미랍니다. 간단하죠?
이제 간단하게 예제를 보도록 합시다.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main(){
sigset_t pendingset;
sigset_t set;
sigemptyset(&set);
sigemptyset(&pendingset);
sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGINT);
sigaddset(&set,SIGTSTP);
sigprocmask(SIG_BLOCK,&set,NULL);
printf("SIGQUIT, SIGINT, SIGTSTP를 발생시켜보세요.\n");
sleep(3);
if(sigpending(&pendingset)==0){
printf("\n\nBlock되어 대기중인 SIGNAL\n");
if(sigismember(&pendingset,SIGQUIT))
printf("SIGQUIT\n");
if(sigismember(&pendingset,SIGINT))
printf("SIGINT\n");
if(sigismember(&pendingset,SIGTSTP))
printf("SIGTSTP\n");
}
sleep(3);
sigprocmask(SIG_UNBLOCK,&set,NULL);
printf("SIGQUIT OR SIGINT OR SIGTSTP 신호를 발생시켰으면 이 메
시지가 보이지 않습니다.\n");
return 0;
}
이 프로그램은 set에 있는 시그널들이 발생하면 블록하고 만약 이 중 시그널이 발생하면 블록된 시그널의 목록을 보여주는 프로그램입니다. 우선 set에는 SIGQUIT, SIGINT, SIGTSTP라는 시그널이 들어있고 sigprocmask로 블록시키라고 명령합니다. 이 후 3초가 지난후 sigpending으로 블록되어 대기중인 signal을 pendingset에 설정합니다. 함수가 성공적으로 호출되었다(반환값 0)면 sigismember에서 어떤 시그널이 대기중인지 확인합니다.
확인해봅시다. gcc 소스코드 -o signal 로 컴파일하고 실행파일을 실행시켜봅시다.
# ./signal
SIGQUIT, SIGINT, SIGTSTP를 발생시켜보세요.
^C^Z
Block되어 대기중인 SIGNAL
SIGINT
SIGTSTP
저는 3초이내 Ctrl+C(SIGINT)와 Ctrl+Z(SIGTSTP)를 발생시키고 메시지를 확인해보니 SIGINT와 SIGTSTP가 대기중이라고 나옵니다. 이해되셨나요?
- sigsuspend
int sigsuspend(const sigset_t *mask);
시그널을 BLOCK시킴과 동시에 대기합니다. sigprocmask같은 경우 how를 SIG_BLOCK이나 SIG_SETMASK로 설정하면 블록하기만 할뿐 대기하지는 않는데, sigsuspend는 블록과 대기를 동시에 할 수 있는 것이죠. 성공시 0, 실패시 -1을 반환합니다.
아래의 예제가 있습니다.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main(){
sigset_t set;
sigemptyset(&set);
sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGINT);
sigaddset(&set,SIGTSTP);
printf("SIGQUIT, SIGINT, SIGTSTP이 5초간 BLOCK됩니다.\n");
sigprocmask(SIG_SETMASK,&set,NULL);
sleep(5);
printf("\n\nSIGNAL 블록이 해제되고 시그널이 발생했다면 종료됩니다.\n");
printf("시그널을 발생시키지 않았다면 발생시켜 종료하세요.\n");
sigemptyset(&set);
sigsuspend(&set);
return 0;
}
SIGQUIT, SIGINT, SIGTSTP를 sigprocmask의 SIG_SETMASK로 블록시키려고 하는군요. 5초 후에 set을 빈 집합으로 설정합니다. 만일 SIGQUIT, SIGINT, SIGTSTP가 5초 이내에 발생했다면 프로그램은 5초후 바로 종료하게 되고, 발생시키지 않았다면 위 3개의 시그널이 발생할때까지 대기하게 되는 것입니다.
- 5초 내에 SIGINT 신호를 전달한 경우 5초가 지난 후 메시지 출력후 바로 종료
# ./a.out
SIGQUIT, SIGINT, SIGTSTP이 5초간 BLOCK됩니다.
^C
SIGNAL 블록이 해제되고 시그널이 발생했다면 종료됩니다.
시그널을 발생시키지 않았다면 발생시켜 종료하세요.
- 5초내에 3개의 신호 아무것도 를 주지 않은 경우 신호를 줄때까지 계속 대기
# ./a.out
SIGQUIT, SIGINT, SIGTSTP이 5초간 BLOCK됩니다.
SIGNAL 블록이 해제되고 시그널이 발생했다면 종료됩니다.
시그널을 발생시키지 않았다면 발생시켜 종료하세요.
이상으로 3개의 signal 관련 함수를 알아보았습니다.
'컴퓨터 > 운영체제(주로 리눅스)' 카테고리의 다른 글
[리눅스] 명령어 pwd, cd, ls 알아보기 (0) | 2019.05.16 |
---|---|
[리눅스] 스레드(Thread) 개념과 예제(pthread_create, pthread_join, pthread_detach) (2) | 2019.01.06 |
[리눅스] 시그널 (SIGNAL) 2 시그널 함수 sigprocmask, sigfillset, sigemptyset, sigaddset, sigdelset (11) | 2018.12.31 |
[리눅스] 시그널1 신호(SIGNAL)의 개념과 자세히 들여다 보기 - 시그널 핸들러 (0) | 2018.12.10 |
[리눅스] 프로세스 생성과 특징, 종료 (fork, wait), 예제 코드 (0) | 2018.12.10 |