1 시그널
2 11.1 시그널
시그널 시그널은예기치않은사건이발생할때이를알리는소프트웨어인터럽트이다. 시그널발생예 SIGFPE 부동소수점오류 SIGPWR 정전 SIGALRM 알람시계울림 SIGCHLD 자식프로세스종료 SIGINT 키보드로부터종료요청 (Ctrl-C) SIGSTP 키보드로부터정지요청 (Ctrl-Z) 3
주요시그널 시그널이름 의미 기본처리 SIGABRT abort() 에서발생되는종료시그널 종료 ( 코어덤프 ) SIGALRM 자명종시계 alarm() 울림때발생하는알람시그널 종료 SIGCHLD 프로세스의종료혹은중지를부모에게알리는시그널 무시 SIGCONT 중지된프로세스를계속시키는시그널 무시 SIGFPE 0으로나누기와같은심각한산술오류 종료 ( 코어덤프 ) SIGHUP 연결끊김 종료 SIGILL 잘못된하드웨어명령어수행 종료 ( 코어덤프 ) SIGIO 비동기화 I/O 이벤트알림 종료 SIGINT 터미널에서 Ctrl-C 할때발생하는인터럽트시그널 종료 SIGKILL 잡을수없는프로세스종료시키는시그널 종료 SIGPIPE 파이프에쓰려는데리더가없을때 종료 SIGPIPE 끊어진파이프 종료 4
주요시그널 SIGPWR 전원고장 종료 SIGSEGV 유효하지않은메모리참조 종료 ( 코어덤프 ) SIGSTOP 프로세스중지시그널 중지 SIGSTP 터미널에서 Ctrl-Z 할때발생하는중지시그널 중지 SIGSYS 유효하지않은시스템호출 종료 ( 코어덤프 ) SIGTERM 잡을수있는프로세스종료시그널 종료 SIGTTIN 후면프로세스가제어터미널을읽기 중지 SIGTTOU 후면프로세스가제어터미널에쓰기 중지 SIGUSR1 사용자정의시그널 종료 SIGUSR2 사용자정의시그널 종료 5
시그널생성 터미널에서생성된시그널 CTRL-C SIGINT CTRL-Z SIGSTP 하드웨어예외가생성하는시그널 0 으로나누기 SIGFPE 유효하지않는메모리참조 SIGSEGV kill() 시스템호출 프로세스 ( 그룹 ) 에시그널보내는시스템호출 프로세스의소유자이거나슈퍼유저이어야한다. 소프트웨어조건 SIGALRM: 알람시계울림 SIGPIPE: 끊어진파이프 SIGCHLD: 자식프로세스가끝났을때부모에전달되는시그널 6 숙대창병모
시그널처리 기본처리동작 프로세스를종료시킨다 (terminate) 시그널무시 (ignore) 프로세스중지 (suspend) 프로세스계속 (resume) 7 숙대창병모
alarm() #include <unistd.h> unsigned int alarm(unsigned int sec) sec 초후에프로세스에 SIGALRM 시그널이발생되도록설정한다. sec 초후에프로세스에 SIGALRM 시그널이발생한다. 이시그널을받으면 자명종시계 " 메시지를출력하고프로그램은종료된다. 한프로세스당오직하나의알람만설정할수있다. 이전에설정된알람이있으면취소되고남은시간 ( 초 ) 을반환한다. 이전에설정된알람이없다면 0 을반환한다. 8 alarm(0) 이전에설정된알람은취소된다. 숙대창병모
alarm.c #include <stdio.h> /* 알람시그널을보여주는프로그램 */ int main( ) { alarm(5); printf(" 무한루프 \n"); while (1) { sleep(1); printf( 1초경과 \n"); printf(" 실행되지않음 \n"); 9
11.2 시그널처리 숙대창병모 10
시그널처리기 시그널에대한처리함수지정 signal() 시스템호출 이시그널이발생하면이렇게처리하라 signal() 시스템호출 #include <signal.h> signal(int signo, void (*func)( ))) signo 에대한처리함수를 func 으로지정하고기존의처리함수를리턴한다 11 시그널처리함수 func SIG_IGN : 시그널무시 SIG_DFL : 기본처리 사용자정의함수이름
예제 : almhandler.c #include <stdio.h> #include <signal.h> void alarmhandler(); /* 알람시그널을처리한다. */ int main( ) { signal(sigalrm,alarmhandler); alarm(5); /* 알람시간설정 */ printf(" 무한루프 \n"); while (1) { sleep(1); printf("1초경과 \n"); printf(" 실행되지않음 \n"); 12 void alarmhandler() { printf(" 일어나세요 \n"); exit(0);
예제 : inthandler.c #include <stdio.h> void inthandler(int signo) #include <stdlib.h> { #include <signal.h> printf(" 인터럽트시그널처리 \n"); void inthandler(); printf( 시그널번호 : %d\n, signo); /* 인터럽트시그널을처리한다. */ exit(0); int main( ) { signal(sigint,inthandler); while (1) pause(); printf(" 실행되지않음 \n"); #include <signal.h> pause() 시그널을받을때까지해당프로세스를잠들게만든다. 13
sigaction() 함수 signal() 보다정교하게시그널처리기를등록하기위한함수 sigaction 구조체를사용하여정교한시그널처리액션을등록 #include <signal.h> int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); signum 시그널 (SIGKILL과 SIGSTOP 제외 ) 이수신되었을때, 프로세스가취할액션을변경하는데사용된다. 이시그널에대한새로운액션은 act가되며, 기존의액션은 oldact에저장된다. 성공하면 0을실패하면 1를반환한다. struct sigaction { void (*sa_handler)(int); // 시그널처리기 void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; // 시그널을처리하는동안차단할시그널집합 int sa_flags; 14
sigint2.c 1 #include <stdio.h> 2 #include <signal.h> 3 struct sigaction newact; 4 struct sigaction oldact; 5 void sigint_handler(int signo); 6 7 int main( void) 8 { 9 newact.sa_handler = sigint_handler; // 시그널처리기지정 10 sigfillset(&newact.sa_mask); // 모든시그널을차단하도록마스크 11 12 // SIGINT의처리액션을새로지정, oldact에기존처리액션을저장 13 sigaction(sigint, &newact, &oldact); 15
sigint2.c 14 while(1 ) 15 { 16 printf( "Ctrl-C를눌러보세요!\n"); 17 sleep(1); 18 19 20 21 /* SIGINT 처리함수 */ 21 void sigint_handler(int signo) 22 { 23 printf( "%d 번시그널처리!\n", signo); 24 printf( " 또누르면종료됩니다.\n"); 25 sigaction(sigint, &oldact, NULL); // 기존처리액션으로변경 26 16
11.3 시그널보내기 17
시그널보내기 : kill 명령어 killl 명령어 한프로세스가다른프로세스를제어하기위해특정프로세스에임의의시그널을강제적으로보낸다. $ kill [- 시그널 ] 프로세스 ID $ kill l // 시그널리스트 HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS... 18
시그널보내기 : kill() kill() 시스템호출 특정프로세스 pid 에원하는임의의시그널 signo 를보낸다. 보내는프로세스의소유자가프로세스 pid 의소유자와같거나혹은보내는프로세스의소유자가슈퍼유저이어야한다. #include <sys/types.h> #include <signal.h> int kill(int pid, int signo); 프로세스 pid에시그널 signo를보낸다. 성공하면 0 실패하면 -1를리턴한다. 19
kill() pid > 0 : signal to the process whose process ID is pid pid == 0 : signal to the processes whose process group ID equals that of sender pid < 0 : signal to the processes whose process group ID equals abs. of pid pid == -1 : POSIX.1 leaves this condition unspecified (used as a broadcast signal in SVR4, 4.3+BSD) 20
예제 : 제한시간명령어실행 tlimit.c 프로그램 명령줄인수로받은명령어를제한시간내에실행 execute3.c 프로그램을알람시그널을이용하여확장 프로그램설명 자식프로세스가명령어를실행하는동안정해진시간이초과되면 SIGALRM 시그널이발생 SIGALRM 시그널에대한처리함수 alarmhandler() 에서자식프로세스를강제종료 kill(pid, SIGINT) 호출을통해자식프로세스에 SIGINT 시그널을보내어강제종료 만약 SIGALRM 시그널이발생하기전에자식프로세스가종료하면이프로그램은정상적으로끝남 21
tlimit.c #include <stdio.h> #include <unistd.h> #include <signal.h> int pid; void alarmhandler(); /* 명령줄인수로받은명령어실행에제한시간을둔다. */ int main(int argc, char *argv[]) { int child, status, limit; signal(sigalrm, alarmhandler); sscanf(argv[1], "%d", &limit); alarm(limit); pid = fork( ); 22 if (pid == 0) { execvp(argv[2], &argv[2]); fprintf(stderr, "%s: 실행불가 \n", argv[1]); else { child = wait(&status); printf("[%d] 자식프로세스 %d 종료 \n", getpid(), pid); void alarmhandler() { printf("[ 알람 ] 자식프로세스 %d 시간초과 \n", pid); kill(pid,sigint);
시그널을이용한프로세스제어 시그널을이용하여다른프로세스를제어할수있다. SIGCONT SIGSTOP SIGKILL SIGTSTP SIGCHLD 프로세스재개프로세스중지프로세스종료 Ctrl-Z에서발생자식프로세스중지혹은종료시부모프로세스에전달 예제 : 시그널을이용한자식프로세스제어 23
control.c #include <signal.h> #include <stdio.h> /* 시그널을이용하여자식프로세스들을제어한다. */ int main( ) { int pid1, pid2; pid1 = fork( ); if (pid1 == 0) { while (1) { sleep(1); printf(" 프로세스 [1] 실행 \n"); pid2 = fork( ); 24 if (pid2 == 0) { while (1) { sleep(1); printf(" 프로세스 [2] 실행 \n"); sleep(2); kill(pid1, SIGSTOP); sleep(2); kill(pid1, SIGCONT); sleep(2); kill(pid2, SIGSTOP); sleep(2); kill(pid2, SIGCONT); sleep(2); kill(pid1, SIGKILL); kill(pid2, SIGKILL);
11.4 시그널과비지역점프 25
비지역점프 :setjmp/longjmp 임의의위치로비지역점프 오류 / 예외처리, 시그널처리등에유용함 int setjmp( jmp_buf env) longjmp 전에호출되어야함 longjmp 할곳을지정함. 한번호출되고여러번반환함. void longjmp( jmp_buf env, int val) setjmp 후에호출됨 Setjmp 에의해설정된지점으로비지역점프 한번호출되고반환하지않음. 26
setjmp/longjmp #include <setjmp.h> int setjmp( jmp_buf env); 비지역점프를위해스택내용등을 env에저장한다. setjmp() 는처음반환할때 0을반환하고저장된내용을사용하는 longjmp() 에의해두번째반환할때는 0 이아닌 val 값을반환한다. void longjmp( jmp_buf env, int val); env 에저장된상태를복구하여스택내용등이저장된곳으로비지역점프한다. 구체적으로상응하는 setjmp() 함수가 val 값을반환하고실행이계속된다. 27
jump1.c #include <stdio.h> #include <stdlib.h> #include <setjmp.h> void p1(), p2(); jmp_buf env; int main() { if (setjmp(env)!= 0) { printf(" 오류로인해복귀 \n"); exit(0); else printf(" 처음통과 \n"); 28 p1();
jump1.c void p1() { p2(); void p2() { int error; 29 error = 1; if (error) { printf(" 오류 \n"); longjmp(env, 1);
jump2.c #include <stdio.h> #include <stdlib.h> #include <setjmp.h> #include <signal.h> void p1(); void inthandler(); jmp_buf env; int main() { signal(sigint, inthandler); if (setjmp(env)!= 0) { printf(" 인터립트로인해복귀 \n"); exit(0); else printf(" 처음통과 \n"); p1(); 30
jump2.c void p1() { while (1) { printf(" 루프 \n"); sleep(1); void inthandler() { printf(" 인터럽트 \n"); longjmp(env, 1); 31
핵심개념 시그널은예기치않은사건이발생할때이를알리는소프트웨어인터럽트이다. signal() 시스템호출은특정시그널에대한처리함수를지정한다. kill 명령어나 kill() 시스템호출을이용하여특정프로세스에원하는시그널을보낼수있다. longjmp() 함수는 setjmp() 함수에의해설정된지점으로비지역점프를한다. 32