260 likes | 631 Views
Linux/UNIX Programming APUE (Signals ). Signals. APUE (Signals). Signals are software interrupts( 가로채기 ) an illegal operation (e.g., divide by 0 ) an alarm clock the death of a child process a termination request from a user a suspend request from a user. Process. Signal ##.
E N D
Linux/UNIX Programming APUE (Signals)
Signals APUE (Signals) • Signals are software interrupts(가로채기) • an illegal operation (e.g., divide by 0) • an alarm clock • the death of a child process • a termination request from a user • a suspend request from a user Process Signal ##
Predefined Signals (1/2) APUE (Signals) • define • /usr/include/signal.h(/usr/include/sys/iso/signal_iso.h) • Every signal has a name • begin with ‘SIG’ • SIGABRT: abort signal from abort() • SIGALRM: alarm signal from alarm() • Actions of the default signal handler • terminate the process and generate a core(dump) • ignores and discards the signal(ignore) • suspends the process (suspend) • resume the process
Predefined Signals (2/2) APUE (Signals) /usr/include/asm/signal.h
Signal Generation APUE (Signals) • Terminal-generated signals • CTRL-C SIGINT • CTRL-Z SIGSTP signal • Hardware excepts generate signals • divide by 0 SIGFPE • invalid memory reference SIGSEGV • kill() • sends any signal to a process or process group • need to be owner or super-user • Software conditions • SIGALRM: alarm clock expires • SIGPIPE: broken pipe • SIGURG: out-of-band network data
Handling of Signals APUE (Signals) Ignore the signal:모든 시그널은 무시할 수 있음, 단SIGKILL and SIGSTOP은 예외 signal catching function:시그널 발생시 호출될 함수를 지정할 수 있음 Let the default action apply:most are to terminate process
Representative UNIX Signals (1/2) APUE (Signals) SIGART : 비정상 종료(종료+코어덤프) SIGALRM : 타이머 만료(종료) SIGCHLD : 자식의 상태 변화(무시) SIGCONT : 중단된 프로세스의 실행 재개(재개/무시) SIGFPE : 산술예외, such as divide-by-0 (종료+코어덤프) SIGILL :적법하지 않은 명령(종료+코어덤프) SIGINT: 터미널 가로채기(종료)
Representative UNIX Signals (2/2) APUE (Signals) SIGKILL : 종료, 무시할수 없음(종료) SIGPIPE : 리더가 없는 파이프 쓰기(종료) SIGSEGV : 유효하지 않은 메모리 참조(종료+코어덤프) SIGTERM : 종료(종료) SIGSTOP : 중단(프로세스 중단) SIGUSR1 : user defined signal 1(종료) SIGUSR2 : user defined signal 2(종료)
signal() APUE (Signals) • Signal Handler 등록 • signal(int signo, void(*func)())) • specify the action for a signal (signo func) • func • SIG_IGN (ignore) • SIG_DFL (default) • user-defined function • Return: the previous func
예제: alarm1.c (w/o handler) APUE (Signals) #include <stdio.h> // alarm1.c main( ) { alarm(3); printf(“Looping forever …\n”); while (1); printf(“This line should never be executed\n”); }
예제: alarm2.c (w/ handler) (1/2) APUE (Signals) #include <stdio.h> // alarm2.c #include <signal.h> intalarmFlag=0; void alarmHandler(); main( ) { signal(SIGALRM, alarmHandler); alarm(3); printf("Looping …\n"); while(!alarmFlag) { pause( ); } printf("Loop ends due to alarm signal \n"); } void alarmHandler( ) { printf("An alarm clock signal was received\n"); alarmFlag = 1; }
예제: alarm2.c (w/ handler) (2/2) APUE (Signals) 실행 결과
SIGCHLD APUE (Signals) Whenever a process terminates or stops, the signal is sent to the parent. 자식 프로세스는 자신이 죽을 때, 부모 프로세스에게 SIGCHLD를 보낸다.
예제: timelimit.c (1/3) APUE (Signals) $ timelimit N command// command를 N seconds안에 수행하라! #include <stdio.h> // timelimit.c #include <signal.h> int delay; void childHandler( ); main(intargc, char *argv[]) { intpid; sscanf(argv[1], "%d", &delay); signal(SIGCHLD,childHandler); pid = fork(); if (pid == 0) { // child execvp(argv[2], &argv[2]); perror("Limit"); } else { // parent sleep(delay); printf("Child %d exceeded limit and is being killed\n", pid); kill(pid, SIGINT); } }
예제: timelimit.c (2/3) APUE (Signals) childHandler( ) /* Executed if the child dies before the parent */ { intchildPid, childStatus; childPid = wait(&childStatus); printf(“Child %d terminated within %d seconds\n”, childPid, delay); exit(0); }
예제: timelimit.c (3/3) APUE (Signals) 실행 결과
kill(), raise() APUE (Signals) #include <sys/types.h> #include <signal.h> int kill(pid_tpid, intsigno); int raise(intsigno); Both return: 0 if OK, 1 on error • kill - sends a signal to a process or a group of processes • raise - function allows a process to send a signal to itself • raise(signo) == kill(getpid(), signo);
kill() APUE (Signals) • pid means • pid > 0 : 프로세스 ID가 pid인 프로세스에 신호를 보낸다. • pid == 0 : 프로세스 그룹 ID가 동일한 모든 프로세스에게 신호를 보낸다. • pid < 0 : 프로세스 그룹 ID가 pid인 모든 프로세스에게 신호를 보낸다. • pid == -1 : 모든 프로세스에 신호를 보낸다.(boradcast) • Permission to send signals • The super-user can send a signal to any process. • The real or effective user ID of the sender has to equal the real or effective user ID of the receiver.
alarm() APUE (Signals) #include <unistd.h> unsigned int alarm (unsigned int seconds); Returns: 0 or number of seconds until previously set alarm • alarm() 는 지정된 시간 이후에 만료될 타이머를 설정하는데 사용 • when timer expires, SIGALRM signal is generated, • default action of the signal is to terminate the process. • Only one alarm clock per process • 이전에 설정한 타이머가 만료되지 않은 상황에서 alarm을 호출하면 타이머는 새로운 값으로 설정됨 • if alarm(0), a previous unexpired alarm is cancelled.
pause() APUE (Signals) #include <unistd.h> int pause (void); Returns: -1 with errno set to EINTR • 신호가 전달될 때까지 프로세스를 일시정지 시킴 • Signal handler의 실행이 끝날 때까지 차단된다. • signal handler가 등록된 경우 해당 handler가 처리를 마친 후 리턴한다.
예제: mysleep.c (1/2) APUE (Signals) #include <signal.h> // mysleep.c #include <unistd.h> static void sig_alrm(intsigno) { return; /* nothing to do, just return to wake up the pause */ } unsigned intmysleep(unsigned intnsecs) { if (signal(SIGALRM, sig_alrm) == SIG_ERR) return nsecs; alarm(nsecs); /* start the timer */ pause(); /* next caught signal wakes us up */ return alarm(0); /* turn off timer, return unslept time */ } • 상기 mysleep() 함수는 다음과 같은 몇 가지 문제점을 안고 있다. • 만일 mysleep()을 사용하기 이전에 alarm을 set한 경우, 앞서의 alarm이 지워진다. • Race condition이 발생할 수 있다(즉, pause()가 호출되기 전에 alarm이 발생할 수 있다.). • 상기 문제 해결을 위해서는 보다 견고한 mysleep()의 구현이 필요하다.
예제: mysleep.c (2/2) APUE (Signals)
abort() APUE (Signals) #include <stdlib.h> void abort(void); This function never returns • abnormal program termination. • This function sends the SIGABRT signal to the process. • raise(SIGABRT) • SIGABRT signal handler to perform any cleanup that it wants to do, before the process terminated.
sleep() APUE (Signals) #include <signal.h> unsigned int sleep(unsigned int seconds) ; Returns: 0 or number of unslept seconds • 호출한 프로세스를 일시 정시 상태로 만듬, 아래 두가지조건중 하나가 발생하면 깨어남 • 타이머가 만료 된 경우 • 프로세스가 신호를 잡았으며 해당 신호 처리부가 반환 될 경우
sigaction() APUE (Signals) #include <signal.h> intsigaction(int sig, structsigaction * act, structsigaction * act) ; return: 0 if OK, 1 on error • sigaction구조체를 사용해 핸들러를 등록 strcutsigaction { void (* sa_handler)(int) //핸들러 sigset_tsa_mask //차단할 신호들 intsa_flags; //옵션들 }
sigaction() APUE (Signals) #include <signal.h> #include <stdio.h> #include <unistd.h> void ouch(int sig) { print(“OUCH! – I got signal %d\n”, sig); int main() { structsigaction act; act.sa_handler = ouch; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, 0); wihle(1) { printf(“hello world\n”); sleep(1); } }