Linux System Programming

Slides:



Advertisements
Similar presentations
YES C 제 1 장 C 언어의 개요 1/34 제 1 장 C 언어의 개요 문봉근. YES C 제 1 장 C 언어의 개요 2/34 제 1 장 C 언어의 개요 1.1 프로그램과 C 언어의 특징 1.2 C 언어의 프로그램 구성 1.3 비주얼 C++ 통합 환경 들어가기.
Advertisements

12장 프로세스.
Linux/UNIX Programming APUE (The Environment of a UNIX Process)
제3장 C 프로그래밍 환경.
제 1장 C 언어의 소개.
C 프로그래밍 소개 숙명여대 창병모 2011 가을.
Chapter 10– 표준 함수(1) Outline 10.1 스트림과 파일 10.2 입출력 표준 함수
제 8 장  파서 생성기 YACC 사용하기.
C 프로그래밍.
Linux System Programming
Department of Computer Engineering
7. UNIX PROCESS CONTROL ▷ fork : 새로운 프로세스 생성 ▷ exit : 프로세스 실행을 종료
인공지능실험실 석사 2학기 김승겸 TCP/IP Socket Programming… 제 10장 멀티태스킹 기반의 서버구현 인공지능실험실 석사 2학기 김승겸
Signal & Inter-Process Communication
디바이스 드라이버 기초 디바이스 드라이버의 개요 파일 연산 디바이스 드라이버 등록 디바이스 드라이버 구성
Linux System Programming
Department of Computer Engineering
제9장 C 프로그래밍 환경 창병모
제5장 제어명령
6 프로세스 생성과 실행.
Linux System Programming
Global array – 1M의 integer, P0.dat, P1.dat, P2.dat, P3.dat
18장 Practical Network Project
제 12장 I/O멀티플렉싱(Multiplexing)
7. while 문의 흐름 제어.
Department of Computer Engineering
Department of Computer Engineering
12장 파이프.
fork로 생성한 자식 프로세스에서 exec 함수군을 호출
Linux System Programming
멀티쓰레드 기반의 서버구현 School of Electronics and Information.
파일 및 디렉토리(1) 여러 함수들 chdir(“category”) || die “cannot cd to temp”;
12장 프로세스.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express.
Term Project Team Member
C언어 프로그래밍의 이해 Ch05. 명령문 Phylogenetic: 계통, 발생(학)의.
Advanced Socket Programming
6장 파일 및 레코드 잠금.
Department of Computer Engineering
제 3 장 상수와 변수
10장 C 표준 파일 입출력 子曰 學而時習(실습?)之 不亦悅乎.
쉽게 풀어쓴 C언어 Express 제7장 반복문 C Express.
5 프로세스 정보.
4장 제어문 선택문: if 문, if – else 문, switch 문
제 11 장 전처리기.
adopted from KNK C Programming : A Modern Approach
Signal & Inter-Process Communication
제4장 유닉스 쉘 숙명여대 창병모 2011 가을.
Memory & Data Management.
11장 시그널.
제어문 & 반복문 C스터디 2주차.
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
조 병 규 Software Quality Lab. 한국교통대학교
리눅스 커널의 이해 중에서 9장. 시그널 Database 실험실 안 병 규.
U N I X 창원대학교 전자계산학과 김병찬.
6장 반복제어문 for 문 while 문 do while 문 기타 제어문.
Department of Computer Engineering
C언어 프로그래밍의 이해 Ch05. 명령문.
GDB - GNU Debugger 김진용.
반복문의 기능 반복문 반복문 특정 영역을 특정 조건이 만족하는 동안에 반복 실행하기 위한 문장 while문
제4장 유닉스 쉘 숙명여대 창병모
제5장 디버깅과 추적 문봉근.
실습과제 1번 생성된 파일 basic.txt를 프로젝트 폴더에서 메모장으로 열고 내용을 확인
argc, argv 의 사용방법 #include <stdio.h>
Signal & Inter-Process Communication
C 13장. 입출력 라이브러리 #include <stdio.h> int main(void) { int num;
C.
printf("Global Korea\n");
3장 파일 다루기 한빛미디어(주).
⊙ 입출력 처리란? data를 입력장치로부터 program 내부로 읽어 들이거나
Presentation transcript:

Linux System Programming Lecture #7 – 시그널(Signal) 처리

신호(Signal) (1) 신호(Signal) 정의: 비동기적인 사건(event)들의 발생을 프로세스에게 알려주는 기능 프로세스간의 통신 기법 중에 하나 사용자 프로세스 간에 또는 커널과 사용자 프로세스 간에 특정 사건이 발생하였음을 알리는 방법으로 사용 소프트웨어 인터럽터 개념 신호의 유형: 프로세스 종료 관련 신호 프로세스 예외 관련 신호 시스템 호출 관련 신호 복구할 수 없는 상태 관련 신호 예기치 않은 에러 관련 신호 사용자 프로세스 유발 신호 터미널 작업 관련 신호 프로세스 실행 추적 관련 신호 Linux System Programming

신호(Signal) (2) 신호(Signal) 처리: 프로세스가 커널 모드에서 사용자 모드로 전환될 때에 커널이 신호 여부를 확인하고 처리한다 프로세스가 사용자 모드에서 실행 중에 발생한 신호는 커널이 인터럽터 처리를 종료한 후에 돌아올 때에 커널에 의해 처리된다 Linux System Programming

신호의 종류 (1) 신호의 종류: 헤드 파일 <signal.h>에 지원되는 시그널을 정의 Linux System Programming

신호의 종류 (2) 신호의 종류 – 처리 방식에 따른 유형: 신호의 처리 방식 유형 Exit – 정상 종료 Core – 비정상적인 종료 + 코더 덤프 Stop – 무조건 종료 Ignore – 신호 무시 대부분의 신호는 신호가 발생하면 프로세스를 정상 종료시킨다(Exit). 프로세스가 종료할 때에 종료를 유발한 시그널 종류를 전달하기 위해 프로세스 반환값의 상위 8비트에는 시그널 번호를 , 하위 8비트에는 0을 설정하여 반환한다 SIGQUIT, SIGILL, SIGTRAP, SIGSYS, SIGFPE 등의 신호는 비정상 종료를 초래하고, 이로 인해 코어 덤프가 생성된다(Core). 특정 시그널에 대해서는 프로세스 시작 시점에 무시하도록 설정할 수 있다(Ignore) Linux System Programming

신호의 설정과 수신 (1) 신호의 설정: 모든 신호에 대해서는 기본적인(default) 처리 방식이 설정되어 있다(Exit/Core/Stop/Ignore) 프로세스는 시스템 호출을 이용하여 특정 신호에 대해 처리 방식을 변경할 수 있다 프로그램 실행 과정에서 예기치 못한 신호로 인해 문제가 발생할 수 있다 signal, sigset, sigaction 시스템 호출을 사용하여 신호의 세가지 처리 방식(신호의 기본적인 동작(SIG_DFL), 신호의 무시(SIG_IGN), 신호의 수신) 중에서 하나를 지정할 수 있다 신호의 수신 모드인 경우에는 새로운 신호 처리 함수(signal handler)을 지정할 수 있다 Linux System Programming

신호의 설정과 수신 (2) 신호의 설정: signal() Linux System Programming

신호의 설정과 수신 (3) 예제 7-1 신호 SIGINT을 받았을 때에 현재 출력 중인 파일을 닫은 후에 프로그램 종료하도록 한다 #include <stdio.h> #include <signal.h> #define OUTPUT "Primes" #define MAXNUM 10000 int count; FILE *fptr; main() { int number, divisor; void sigcatch(); fptr = fopen(OUTPUT,"w"); signal(SIGINT, sigcatch); Linux System Programming

신호의 설정과 수신 (4) for(number =1; number <= MAXNUM; number++) { for(divisor =2; divisor < number; divisor++) if((number % divisor) == 0) break; if(divisor == number) { fprintf(fptr,"%d\n",number); count++; } fclose(fptr); void sigcatch() { printf("%d primes computed\n", count); exit(1); Linux System Programming

신호의 설정과 수신 (5) 예제 7-2 예제 7-1에서 여러 번의 SIGINT 신호를 받을 수 있고, SIGQUIT 신호르 수신하면 프로그램을 종료하도록 수정하여라. : void sigcatch(sig) int sig; { signal(sig,SIG_IGN); printf("%d primes computed\n", count); if(sig == SIGQUIT) { fclose(fptr); exit(1); } signal(sig,sigcatch); Linux System Programming

신호의 설정과 수신 (6) 예제 7-4 예제 6-17 프로그램에서 자식 프로세스가 수행되는 동안 부모 프로세스가 SIGINT나 SIGQUIT 신호에 의해 비정상 종료가 되지 않도록 이들 신호를 무시하는 프로그램을 작성하여라. #include <signal.h> command(cmd) /* run a shell command from C program */ char *cmd; { int chpid, fork(); int w, status, wait(); void (*istat) (), (*qstat) (); if ((chpid = fork() ) == 0) { execlp("sh","sh", "-c", cmd, (char *) 0); exit(127); } istat = signal(SIGINT, SIG_IGN); qstat = signal (SIGQUIT,SIG_IGN); Linux System Programming

신호의 설정과 수신 (7) while ((w = wait(&status)) != chpid && w != -1) ; /* null */ signal(SIGINT, istat); signal(SIGQUIT, qstat); return((w != -1) ? (status >> 8) : -1); } main() { printf("%d\n", command("date > Date; cat Date")); printf("%d\n", command("date -u")); printf("%d\n", command("sleep 10; echo done")); Linux System Programming

신호의 송신 (1) 신호의 송신: kill() Linux System Programming

신호의 송신 (2) 예제 7-5 여러 개의 자식 프로세스를 생성하여 수행시키고 부모 프로세스가 신호를 보내어 종료시키는 프로그램을 작성하여라 자식 프로세스는 난수를 발생시켜 그 시간만큼 수면하도록 한다 // file name: ex7-5a.c // #include <signal.h> #define NUMCHILD 20 main(int argc, char *argv[]) { int child1, child2, fork(); int i, pid, chpid[NUMCHILD], status, wait(); for(i=0; i< NUMCHILD; i++) { if((pid = fork()) == 0) execlp("ex7-5b","ex7-5b",(char *) 0); chpid[i] = pid; } Linux System Programming

신호의 송신 (3) printf("parent: wating for children\n"); while((pid = wait(&status)) != -1) { printf("child %d: terminated, status:%d\n",pid,status); if((status>>8) !=0) { for(i=0; i<NUMCHILD; i++) kill(chpid[i],SIGTERM); } printf("parent: all children terminated\n"); exit(0); Linux System Programming

신호의 송신 (4) // file-name: ex7-5b.c // main(int argc, char *argv[]) { int rand(); void srand(); srand((unsigned) getpid()); sleep((rand()*197 %100) +1); exit(1); } Linux System Programming

타이머 신호: alarm (1) 타이머 신호 지정: alarm() 프로세스의 알람 타이머를 조작하는 시스템 호출 지정된 시간이 경과한 후에 SIGALRM 신호가 발생 Linux System Programming

타이머 신호: alarm (2) 타이머 신호 지정: alarm() 이미 알람 타이머가 동작 중인 경우에는 남아 있는 시간을 반환한다 exec 시스템 호출을 수행하더라도 수행되며, fork 시스템 호출에 의해 생성된 자식 프로세스에는 상속되지 않는다 alarm 시스템 호출은 누적되지 않으며, 두 번이상 호출되면 마지막 호출에 지정된 시간이 타이머에 새로이 지정된다 하나의 프로그램 내에서 어떤 작업이 수행되는 시간에 한계를 두려고 할 때에 유용하다 Linux System Programming

타이머 신호: alarm (3) 예제 7-7 자식 프로세스를 생성하여 리눅스 명령어를 실행시키고 부모 프로세스에서는 알람 시간을 설정하여 감시하도록 하며, 주어진 시간에 자식 프로세스가 종료하지 않으며 SIGKILL 신호를 보내어 강제 종료하도록 하는 프로그램을 작성하여라. #include <signal.h> #include <errno.h> #define TIMEOUT 10 int pid; void sigalarm(); main(int argc, char *argv[]) { extern int errno; int status; if((pid = fork()) == 0) { execvp(argv[1], &argv[1]); perror(argv[1]); exit(127); } Linux System Programming

타이머 신호: alarm (4) signal(SIGALRM, sigalarm); alarm(TIMEOUT); while(wait(&status) == -1) { if(errno == EINTR) { errno = 0; printf("%s: timed out\n",argv[1]); } else { perror(argv[0]); break; printf("time remaining: %d\n", alarm(0)); exit(status >>8); void sigalarm(sig) int sig; { kill(pid,SIGKILL); Linux System Programming

프로세스의 정지 (1) 프로세스의 정지: pause() 프로세스로 하여금 SIGALRM 등의 신호가 도착할 때까지 시스템 자원을 낭비하지 않도록 수행을 중지시키는 시스템 호출 pause 시스템 호출을 수행한 프로세스는 새로운 신호가 도착하면 중단 지점부터 실행을 재개한다 Linux System Programming

프로세스의 정지 (2) 예 7-9 alarm과 pause 시스템 호출을 사용하여 C 라이브러리 함수 sleep()과 같은 기능을 수행하는 프로그램을 작성하여라 Signal 시스템 호출과 setjmp, longjmp 함수를 이용하여 구현. #include <signal.h> #include <setjmp.h> static jmp_buf env; static void sigcatch(int); int mysleep(int); main(int argc, char *argv[]) { int atoi(), unslept, mysleep(); void sigint(); signal(SIGINT, SIG_IGN); unslept = mysleep(atoi(argv[1])); printf("remaining time: %d\n",unslept); } Linux System Programming

프로세스의 정지 (3) int mysleep(int seconds) { void (*astat)(); int unslept = seconds; astat = signal(SIGALRM, sigcatch); if(setjmp(env) == 0) { alarm(seconds); pause(); } unslept = alarm(0); signal(SIGALRM, astat); return(unslept); static void sigcatch(int sig) longjmp(env,1); Linux System Programming

프로세스의 수면 프로세스의 수면: sleep() 프로세스를 일정 시간 동안에 정지시키는 시스템 호출 Linux System Programming

신호의 관리 (1) 신호 관리 시스템 호출 리눅스 시스템 V Rel. 3부터 새로운 신호 관리 시스템 호출을 지원 Linux System Programming

신호의 관리 (2) 신호 관리 시스템 호출 Linux System Programming

신호의 관리 (3) 예제 7-10 예제 7-2 프로그램을 sigset 시스템 호출을 개선하여라. #include <stdio.h> #include <signal.h> #define OUTPUT "Primes" #define MAXNUM 10000 int count; FILE *fptr; main() { int number, divisor; void sigcatch(); fptr = fopen(OUTPUT,"w"); sigset(SIGINT, sigcatch); sigset(SIGQUIT, sigcatch); Linux System Programming

신호의 관리 (4) for(number =1; number <= MAXNUM; number++) { for(divisor =2; divisor < number; divisor++) if((number % divisor) == 0) break; if(divisor == number) { fprintf(fptr,"%d\n",number); count++; } fclose(fptr); void sigcatch(sig) int sig; { signal(sig,SIG_IGN); printf("%d primes computed\n", count); if(sig == SIGQUIT) { exit(1); Linux System Programming

신호의 관리 (5) 예제 7-12 Sigset()dhk sigrelse() 시스템 호출을 이용하여 비지역 분기(non-local GOTO) 프로그램을 작성하여라 #include <signal.h> #include <setjmp.h> #define MAXLINE 256 jmp_buf env; main() { void sigcatch(); char line[MAXLINE]; sigset(SIGINT, sigcatch); setjmp(env); Linux System Programming

신호의 관리 (6) for(;;) { printf("Prompt: "); gets(line); /* * process the input here */ } void sigcatch(sig) int sig; { int ch; printf("\nDo you want to exit (y or n)? "); ch = getchar(); getchar(); if(ch == 'y') exit(1); sigrelse(SIGINT); longjmp(env,1); Linux System Programming

신호의 관리 (7) 예제 7-13 인터럽트 신호(SIGINT)가 수신되기를 기다리는 프로그램을 sigpause 시스템 호출을 이용하여 작성하여라 #include <signal.h> int flag; main() { void sigcatch(); sigset(SIGINT, sigcatch); sigset(SIGQUIT, sigcatch); while(1) { /* * processing here */ sleep(3); Linux System Programming

신호의 관리 (8) sighold(SIGINT); if(flag == 0) { printf("pausing for SIGINT\n"); sigpause(SIGINT); } flag = 0; sigrelse(SIGINT); void sigcatch(sig) int sig; { printf("entring sigcatch()\n"); if(sig == SIGQUIT) exit(1); flag ++; Linux System Programming

신호의 관리 (9) 예제 7-15 여러 개의 파일을 라운드-로빈 순서로 읽는 프로그램을 작성하여라 폴링(polling) 다중화된 입력 기법 한 파일로 부터 한 줄을 읽은 후에 다음 파일에서 읽기를 시도하는 방법으로 구현 가능 만일 TIME_OUT으로 주어진 시간 동안 읽을 수 없으면 다음 파일을 읽도록 한다 Linux System Programming

신호의 관리 (10) #include <stdio.h> #include <fcntl.h> #include <signal.h> #include <errno.h> #define TIME_OUT 5 /* seconds before switching to a different */ #define MAXOPEN 20 /* maximum number of open files */ int nfiles; char *fname[MAXOPEN]; int fd[MAXOPEN]; int alrmflg; /* set by alrmtrp(), reset on return of read in rdfile */ extern int errno; main(argc, argv) int argc; char *argv[]; { void rdfiles(); if (argc < 2) { fprintf(stderr, "usage: %s filename [filename...]\n", argv[0]); exit(1); } Linux System Programming

신호의 관리 (11) nfiles = 0; while (--argc) { fname[nfiles] = argv[nfiles + 1]; /* +1 to skip command */ if ((fd[nfiles] = open(fname[nfiles], O_RDONLY)) == -1) { fprintf(stderr, "%s: cannot open %s\n", argv[0], fname[nfiles]); exit(2); } ++nfiles; if (nfiles >= 20) { fprintf(stderr, "%s: too mane file names", argv[0]); exit(3); rdfiles(); void wrline(fnam, lp) register char *fnam, *lp; { char buf[256]; sprintf(buf, "%s: %s", fnam, lp); write(1, buf, strlen(buf)); /* print line and file name */ Linux System Programming

신호의 관리 (12) void rdfiles() { register int i; int opfiles, n; char line[256]; void alrmtrp(); void wrline(); signal(SIGALRM, alrmtrp); opfiles = nfiles; /* number of open files */ while (opfiles) { /* as long as there are open files */ for (i = 0; i < nfiles; i++) { if (fd[i] == -1) continue; alarm(TIME_OUT); line[0] = '\0'; if ((n = read(fd[i], line, sizeof(line))) <= 0) { if (errno == EINTR && alrmflg) { /* alrmflg set in alrmtrp routine */ errno = alrmflg = 0; continue; /* try next line */ } else { close (fd[i]); /* assume eof */ fd[i] = -1; /* don't read anymore */ --opfiles; } Linux System Programming

신호의 관리 (13) alarm(0); /* reset alarm */ line[n] = '\0'; wrline(fname[i], line); } void alrmtrp(sig) int sig; { signal(sig, alrmtrp); alrmflg = 1; Linux System Programming

신호의 관리 (14) 예제 7-16 예제 6-20 프로그램을 수정하여 인터럽트 신호(SIGINT)에 의해 프로그램이 종료되지 않도록 하여라. 백그라운드로 수행되는 명령이 SIGINT 또는 SIGQUIT 신호에 의해 종료되지 않도록 수정하여라. 교재 pp.298~301 프로그램 참조 Linux System Programming