시그널
- 프로세스가 실행되는 도중에 다양한 예외상황이 발생할 수 있고, 이것을 적절하게 처리해야함
- 예외 상황에 발생하는 이벤트 또는 신호를 시그널이라고 함
- 정보와 의미가 일대일로 매칭되기 때문에, 빠르게 전달되고 빠르게 처리할 수 있음
- 대부분의 운영체제에는 시그널이 정의되어있음
- UNIX와 Linux 계열의 운영체제는 kill -l명령어를 통해 그 종류를 확인할 수 있음
- 시그널은 다음 두가지 용도에 특히 잘 사용될 수 있음
- 비동기적인 이벤트의 발생을 통지하기 위한 용도
- 프로세스 종료
- 프로세스간의 통신이나 동기화 하기 위한 용도
- 알림
- 비동기적인 이벤트의 발생을 통지하기 위한 용도
- 시그널은 비동기적, 동기적으로 처리될 수 있음
- 비동기적
- 시그널이 특정 시간에 발생하는 것을 기다리지 않음
- 동기적
- 동작을 중단하고 시그널이 발생하는 것을 기다림
- 비동기적
- 시그널은 각 기본 동작이 정의되어 있음
- Abort
- 코어 덤프를 생성하고 프로세스를 종료
- Exit
- 코어 덤프를 생성하지 않고 프로세스를 종료
- Abnormal termination
- 프로세스를 비정상 종료함
- Stop
- 프로세스를 정지함
- Continue
- 프로세스를 재게함
- ignore
- 시그널을 무시함
- Implementation dependent
- 구현에 의존함
- Abort
POSIX 시그널
시그널의 생성과 처리
시그널 핸들러
- 시그널은 각 기본 동작이 정의되어 있음
- 시그널의 동작을 다른 동작으로 변경할 수 있음
- 시그널 핸들러
- 프로세스가 시그널을 수신했을 때, 기본 동작 대신에 특정 동작을 수행하기를 원할때 사용하는 사용자 정의 함수
- 내부적으로 디폴트 액션 또는 커널 정의 시그널 핸들러는 사용자 정의 시그널 핸드러로 덮어짐
- 하지만 SIGKILL과 SIGSTOP 시그널 동작은 재정의할 수 없음
시그널 마스크
- 블록(Block)
- 프로세스가 시그널을 블록하면 프로세스가 해당 시그널의 블록을 해제할 때까지 그 시그널은 peding됨
- 무시(Ignore)
- 프로세스가 시그널을 무시하면, 그 시그널은 전달되지만 프로세스가 해당 시그널을 버리도록 처리함
시그널 함수
kill 명령어
- 프로세스에 시그널을 전송함
- kill [옵션] [PID]
- 옵션
- -[num] : [num] 번호 시그널을 전송함
- 옵션
kill() 함수
#include <signal.h>
#include <sys/types.h>
int kill(pid_t pid, int signum);
- 설명
- 프로세스에 시그널을 전송함
- 인자
- pid : 프로세스의 pid
- signum : 전송할 시그널의 번호
- 반환
- 성공시 0
- 오류시 -1
signal() 함수
#include <signal.h>
typedef void(*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
- 설명
- 프로세스에 전송된 시그널의 기본동작을 다른 동작으로 재정의 함
- 인자
- signum : 시그널의 번호
- handler : 시그널을 수신했을 때의 동작을 정의한 함수의 포인터
- SIG_IGN : 시그널을 무시함
- SIG_DFL : 시그널의 기본동작으로 되돌림
- 반환
- 성공시 이전 시그널 핸들러의 포인터
- 오류시 SIG_ERR
signal() 함수 예시
#include <dirent.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
void mySigHandler(int signum);
int main(int argc, char const *argv[]) {
if (signal(SIGINT, mySigHandler) == SIG_ERR) {
perror("signal() error");
exit(-1);
}
if (signal(SIGUSR1, mySigHandler) == SIG_ERR) {
perror("signal() error");
exit(-1);
}
printf("Hello my PID is %d\\n", getpid());
while (1) {
puts("Pause...");
pause();
}
return 0;
}
void mySigHandler(int signum) {
if (signum == SIGINT) {
printf("Hello SIGINT\\n");
} else if (signum = SIGUSR1) {
printf("Hello SIGUSR1\\n");
}
}
alarm() 함수
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
- 설명
- 프로세스 자신에 SIGALRM 시그널을 전송함
- 인자
- seconds : 몇 초 후에 시그널을 전송할 것인지 지정
- 반환
- 성공시 시그널 전송할 때 까지 남은 시간
- 오류시 -1
alarm() 함수 예시
#include <dirent.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
void myAlrHandler(int signum);
int main(int argc, char const *argv[]) {
if (signal(SIGALRM, myAlrHandler) == SIG_ERR) {
perror("signal() eroor");
exit(-1);
}
alarm(5);
puts("Sleep ...");
sleep(100);
return 0;
}
void myAlrHandler(int signum) { puts("Hello! I'm wake!"); }
sighold() 함수
#include <signal.h>
int sighold(int signum);
- 설명
- 시그널을 블록 상태로 변경
- 인자
- signum : 블록 하고자하는 시그널 번호
- 반환
- 성공시 0
- 오류시 -1
sigrelse() 함수
#include <signal.h>
int sigrelse(int signum);
- 설명
- 시그널의 블록상태를 해제함
- 인자
- signum : 해제하고자 하는 시그널의 번호
- 반환
- 성공시 0
- 오류시 -1
시그널 집합
시그널 집합
- 시그널은 보통 개별적으로 처리됨
- POSIX에서 복수의 시그널을 처리하기 위해 도입한 개념
- 시그널 집합은 시그널을 비트 마스크로 표현
- 비트 하나가 시그널 하나를 가리킴
- 각비트가 특정 시그널과 일대일로 연결되어 있음
- 비트값이 0인 경우에, 해당 시그널이 설정되지 않은 상태
- 비트값이 1인 경우에, 해당 시그널이 설정된 상태
- UNIX 계열의 운영체제에서 시그널 집합은 sigset_t자료형으로 정의되어 있음
- 정수형 또는 구조체의 자료형으로, 운영체제에 따라 다름
시그널 집합 함수
sigemptyset() 함수
#include <signa;.h>
int sigemptyset(sigset_t * set);
- 설명
- 시그널 집합의 모든 비트를 0dmfh tjfwjdgka
- 인자
- set : 시그널 집합의 포인터
- 반환
- 성공시 0
- 오류시 -1
sigfillset() 함수
#include <signal.h>
int sigfillset(sigset_t * set);
- 설명
- 시그널 집합의 모든 비트를 1로 설정
- 인자
- set : 시그널 집합의 포인터
- 반환
- 성공시 0
- 오류시 -1
sigaddset() 함수
#include <signal.h>
int sigaddset(sigset_t * set,int signum);
- 설명
- 시그널 집합에서 지정한 시그널 비트를 1로 설정함
- 인자
- set : 시그널 집합의 포인터
- signum : 시그널의 번호
- 반환
- 성공시 0
- 오류시 -1
sigdelset() 함수
#include <signal.h>
int sigdelset(sigset_t * set, int signum);
- 설명
- 시그널 집합에서 지정한 시그널비트를 0으로 설정
- 인자
- set : 시그널 집합의 포인터
- signum : 시그널의 번호
- 반환
- 성공시 0
- 오류시 -1
sigismember() 함수
#include <signal.h>
int sigismember(sigset_t * set, int signum);
- 설명
- 시그널 집합에서 지정한 시그널의 설정 유무를 확인
- 인자
- set : 시그널 집합의 포인터
- signum : 시그널의 번호
- 반환
- 성공시 0
- 오류시 -1
sigset_t 사용 예시
#include <dirent.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
printf("SIGUSR1 : %d\\n", sigismember(&set, SIGUSR1));
printf("SIGUSR2 : %d\\n", sigismember(&set, SIGUSR2));
return 0;
}
sigprocmask() 함수
#include <signal.h>
int sigprocmask(int how, const sigset_t * set,sigset_t * oldset);
- 설명
- 시그널 집합을 이용하여 시그널을 블록 상태로 설정하거나 해제할 수 있음
- 인자
- how : 시그널 상태 처리에 대한 플래그
- SIG_BLOCK : set인자에 지정한 시그널 집합을 시그널 마스크에 추가함
- SIG_UNBLOCK : set인자에 지정한 시그널 집합을 시그널 마스크에서 헤제함
- SIG_SETMASK : set인자에 지정한 시그널 집합으로 시그널 마스크를 대체함
- set : 시그널 집합의 포인터
- oldset : 변경 전의 시그널 집합을 저장할 공간에 대한 포인터
- how : 시그널 상태 처리에 대한 플래그
- 반환
- 성공시 0
- 오류시 -1
시그널 집합 함수
- 시그널 집합 생성
- sigemptyset(&set);
- sigemptyset(&oldset);
- 시그널 집합에 시그널 추가
- sigaddset(&set, SIGINT);
- sigaddset(&set,SIGUSR1);
- 시그널 집합을 이용하여 블록 상태 목록에 추가
- sigprocmask(SIG_BLOCK,&set,&oldset);
- 시그널 집합에서 시그널 삭제
- sigdelset(&set,SIGINT);
- 시그널 집합을 이용하여 블록상태 목록에서 해제
- sigprocmask(SIG_UNBLOCK, &set,&oldset);
- 시그널 집합을 이용하여 블록 상태 목록 대체
- sigprocmask(SIG_SETMASK, &set,&oldset);
sigprocmask() 함수 예시
#include <dirent.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
void mySigHandler(int signum) {
if (signum == SIGUSR1) {
puts("Hello!\\n");
}
}
int main(int argc, char const *argv[]) {
int cnt = 10;
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL);
signal(SIGUSR1, mySigHandler);
printf("My PID Is %d\\n", getpid());
while (cnt > 0) {
printf("%d\\n", cnt);
fflush(stdout);
cnt -= 1;
sleep(1);
}
return 0;
}
struct sigaction 구조체
#include <signal.h>
struct sigaction{
int sa_flags; //시그널 전달 방법에 대한 플래그
void (*sa_handler)(int); // 시그널을 처리할 동작 지정
void (*sa_sigaction)(int, siginfo_t *, void *); //시그널을 처리할 동작 지정
sigset_t sa_mask; // 시그널 핸들러가 동작중일, 블록할 시그널 집합
};
- sa_handler : 시그널을 처리할 동작에 대한 지정(SA_SIGINFO가 설정되어 있지 않으면, sa_handler에 지정)
- sig_action : 시그널을 처리할 동작에 대한 지정 (SA_SIGINFO가 설정되어 있으면, sa_sigaction에 지정)
- sa_flags
- SA_RESETHAND : 시그널의 기본 처리방법은 SIG_DFL로 재설정 되고, 시그널이 처리되는 동안 시그널을 블록하지 않음
- SA_NODEFER : 시그널이 처리되는 동안 유니스 커널에서 해당 시그널을 자동으로 블록하지 못함
- SA_SIGINFO
- 시그널 번호 외에 추가 인자 두 개가 시그널 핸들러로 전달됨
- SA_RESTART
- 시스템은 시그널 핸들러에 의해 중지된 기능을 재시작 하게 함
- SA_NOCLDWAIT
- 시그널이 SIGCHILD면 시스템은 자식프로세스가 종료될때 좀비 프로세스를 만들지 않음
- SA_NOCLDSTOP
- 시그널이 SIGCHILD면 자식프로세스가 중지 또는 재시작 할때, 부모 프로세스에 SIGCHILD시그널을 전달하지 않음
sigaction() 함수
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,struct sugaction *oldact);
- 설명
- 시그널 핸들러와 시그널을 처리하는 과정을 제어함
- 인자
- signum : 시그널의 번호
- act : 시그널 처리에 대한 정보를 담은 메모리 공간에 대한 포인터
- oldact : 변경 전의 정보를 저장할 메모리 공간에 대한 포인터
- 반환
- 성공시 0
- 오류시 -1
sigaction() 함수 예시
#include <dirent.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
void mySigHandler(int signum) {
int i = 0;
if (signum == SIGUSR1) {
puts("SIGUSR1 handling start\\n");
for (i = 5; i > 0; --i) {
printf("%d .. ", i);
fflush(stdout);
sleep(1);
}
puts("SIGUSR1 handled!");
} else if (signum == SIGUSR2) {
puts("SIGUSR2 handled!");
}
}
int main(int argc, char const *argv[]) {
sigset_t set;
struct sigaction act;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
act.sa_flags = SA_NODEFER;
act.sa_handler = mySigHandler;
act.sa_mask = set;
sigaction(SIGUSR1, &act, NULL);
signal(SIGUSR1, mySigHandler);
printf("My PID is %d\\n", getpid());
while (1) {
pause();
}
return 0;
}
'시스템 소프트웨어' 카테고리의 다른 글
연결 리스트 (Linked list) (0) | 2023.03.08 |
---|---|
배열과 문자열 (Array and String) (0) | 2023.03.07 |
파일과 디렉토리 (File and Directory) (0) | 2023.02.05 |
프로세스 (Process) (0) | 2023.02.05 |
파일 입출력 (File Input Output) (0) | 2023.02.04 |