1 / 28

Exception Control Flow Review & 실습

Exception Control Flow Review & 실습. A 반 질문리스트 반영되었습니다 .! 만 약 , 해결되지 않았다면 , thread 수업 전 방문하여 질문하시고 이해할 수 있도록 합니다 . ! ppt 에 추가하지 못한 질문은 맨 마지막 장 Q&A 리스트에 넣었스니다 . ^. 2011. 11.23 최 윤 정. 들어가기 전에 .. 동기와 비동기의 의미를 실행으로 알아봅니다. 그동안의 C code 는 1. 위에서 아래로 흘러내려오는 흐름 . 즉 , flow 가 있었습니다 .

Download Presentation

Exception Control Flow Review & 실습

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Exception Control FlowReview & 실습 A반 질문리스트 반영되었습니다.! 만약, 해결되지 않았다면, thread 수업 전 방문하여 질문하시고 이해할 수 있도록 합니다. !ppt에 추가하지 못한 질문은 맨 마지막 장 Q&A 리스트에 넣었스니다. ^ 2011. 11.23 최윤 정

  2. 들어가기 전에..동기와비동기의 의미를 실행으로 알아봅니다. • 그동안의 C code는 • 1. 위에서 아래로 흘러내려오는 흐름. 즉, flow 가 있었습니다. • 폭포처럼 한번 떨어져 내려온 이상 for(),while(), goto등 jump하는 기능이 없으면 다시는 위로 올라갈 수 없는 구조였습니다. • 2. 게다가 동기적인 흐름을 따랐습니다. printf(“데이터를 입력하세요 : ”); scanf(“%d”, &data); printf(“ 입력을 받기 전까지 이후 구문은 출력되지 않습니다.\n”); printf(“ ######\n”); • 그러나, system call은, fork()나 signal() 은 달랐습니다. 동기/비동기적으로 수행됩니다. • 동기적 : wait(), sleep(), pause(), fopen()..등 • 비동기적 : signal() // 시그널 받을 때까지 기다리지 않아요. • 다음의 코드를 다운받아 Visual C++에서 수행해보도록 하세요. • http://home.konkuk.ac.kr/~cris/Class/2011/sp/fork-code/block.exe • 방향키를 눌러서 bar를 움직여 보세요.

  3. while(1) • { • …(중략) • if( GetAsyncKeyState(LEFT) ) bar_x--; • else if(GetAsyncKeyState(RIGHT)) bar_x++; • else if(GetAsyncKeyState(ESCAPE)) • { • system("cls"); • gotoxy(25,10); • system("종료합니다."); • break; • } …. • } • return 0; • source : http://home.konkuk.ac.kr/~cris/Class/2011/sp/fork-code/block.zip 이 소스의 동작은 별을 출력하면서도 Bar를 욺직이고 있어요. Bar을 욺직이기 위해 방향 key를 입력하는 동안 별을 출력하는 부분이 멈추어 있지 않습니다. 만약 키를 입력받고자scanf(); 나getchar()를 썼다면? 입력받기전 출력부분도 ‘대기’합니다. Why?! while 루프 내부를 보면, GetAsyncKetState()라는 함수가 쓰여져 있어요. 비동기식으로 키를 입력받아라. 하는 함수죠. (Khbit()과 마찬가지) 해당 키가 눌려졌는지 아닌지를 catch하여 눌려졌다면 동작합니다. 동작상으로는 system call에서 signal과 유사한 부분이 있죠? 과제를 통해 조사해 보았겠지만, 실행예를 통해 확인해 보세요.

  4. 실습 전알아두어야할 것 fork 함수 호출을 통한 프로세스 생성 • process 에 대한 이해 • 프로세스 상태 : Ready , Running, Waiting, Terminated • ps 명령어로 status 보기 (#man ps로 확인하세요) • fork() – exec계열함수() 의 동작 • 부모-자식프로세스 • 자식은.. 기본적으로 부모가 관리해야 한다. (Reaping.) • 만약, 외부에서 부모프로세스만 kill-9 하면부모만 종료. 자식은 부모를 잃었으므로ppid도 함께 잃음. (후 ppid = 1)따라서 강제종료 시에는 가장 하위자식부터 kill -9. (이제 하지 마세요^^) • 부모는 자식을 작업 종료시 까지 기다려주고, 자식프로세스는 부모프로세스에게 종료 요청을 해주자. 자식은 낳는 것보다 잘 키우는 것이 더 어렵고도 중요합니다. 자식이 어떻게 자라는지(status) 죽음에 대해서도 관심을 가져야 해요. • SIGNAL을 이용하여 process 에 신호(message)를 보낼 수 있습니다. • (리눅스: /usr/include/bits/signum.h에 signal macro 정의) • process가죽는 경우는다양합니다. • 예) Kill -9 pid //kill –SIGKILL pid(강제종료) vs. Kill -SIGTERM pid// terminated • System call • 일반 C-라이브러리함수와 systemcall 함수는 다릅니다.! fork(), execl(), wait(), signal( ) 등 ..

  5. ps : process status START(START) : 프로세스가 시작된 시간 TIME(TIME) : CPU가 사용한 시간 USER(USER) : 사용자의 이름 COMMAND(COMMAND) : 사용자가 실행한 명령어 UID(User ID) : 사용자의 ID (Parent Group ID) : 사용자 부모 프로세스의 그룹 ID SID(Session ID) : 세션 ID PRI(PRIority) : 실행하는 우선 순위에 따른 프로세스 NI(Nice) : nice에 의한 우선 순위에 따른 프로세스 RSS(Resident Set Size) : 프로세스가 사용하는 메모리의 크기 SZ(SiZe) : 프로세스가 사용하는 자료와 스택의 크기 SHRD(ShaReD) : 프로세스가 사용하는 공유 메모리 %CPU : 프로세스가 사용하는 CPU 점유율 %MEM : 프로세스가 사용하고 있는 메모리 점유율 WCHAN : 프로세스가 실행하고 있는 커널 루틴 • Option : • -a : 모든 프로세스 상태 출력 • -e : 현재 실행중인 모든 프로세서 상태 출력 • -f : 프로세스 상태 full list로 출력 • -l : 프로세스 상태 long list로 출력 • -m : 메모리 정보를 출력 • -t TTY : 지정한 TTY를 가진 프로세스 정보 출력 • -u : 사용자 이름, 시작시간을 보여준다 • -p PID : 지정한 PID를 가진 프로세스 정보 출력 • -u UID : 지정한 UID를 가진 프로세스 정보 출력 • -g GID : 지정한 GID를 가진 프로세스 정보 출력 • 프로세스 상태보기 • PID(Process ID) : 프로세스마다 주어지는 번호 • TTY(Tele TYpewrite) : 명령어가 실행되는 터미널의 번호 • STAT(STATe) : 실행되고 있는 프로세스 상태 • R : 실행 중 혹은 실행될 수 있는 상태 • S : sleep • I : idle (비활동 상태 : BSD / 중간적 상태 : sysV) • T : 정지된 상태 (suspend) • Z : 좀비(zombie) 프로세스 • D : 디스크 관련 대기 상태 (BSD) • P : 페이지 관련 대기 상태 (BSD) • X : 메모리 확보를 위해 대기 중 (sys V) • K : 사용 가능한 커널 프로세스 (aix) • W : 스왑out된 상태 • N : nice 되어진 상태 • > : 우선 순위가 인위적으로 높아진 상태

  6. kill : 현재 수행중인 프로세서에게 시그널을 보낸다 • # kill [ -signal ID ] PID // 보통 kill 명령은 프로세서를 죽이는 데에 사용된다. • # kill –L // 시그널 종류 나열 , /usr/include/bits/signum.h에 정의됨 • 시그널의 종류를 지정하지 않으면 프로세서를 종료시키는 의미로 디폴트 시그널 ID 15번을 보내게 된다. • 1. SIGHUP(HUP) : 연결 끊기. 프로세스의 설정파일을 다시 읽는데 사용된다. • 2. SIGINT(INT) : 인터럽트 • 3. SIGQUIOT(QUIT) : 종료 • 4. SIGILL(ILL) : 잘못된 명령 • 5. SIGTRAP(TRAP) : • 6. SIGIOT(IOT) : IOT 명령 • 7. SIGBUS(BUS) : 버스 에러 • 8. SIGFPE(FPE) : 고정 소수점 예외 • 9. SIGKILL(KILL) : 죽이기. 이 시그널은 잡히지 않는다. • 10. SIGUSR1(USR1) : 사용자 정의 시그널 1 • 11. SIGSEGV(SEGV) : 세그멘테이션 위반 • 12. SIGUSR2(USR2) : 사용자 정의 시그널 2 • 13. SIGPIPE(PIPE) : 읽을 것이 없는 파이프에 대한 시그널 • 14. SIGALRM(ALRM) : 경고 클럭 • 15. SIGTERM(TERM) : 소프트웨어 종료 시그널, 일반적으로 kill 시그널이 전송되기 전에 전송된다. • 16. SIGKFLT : 코프로세서 스택 실패 • 17. SIGCHLD(CHLD) : 자식 프로세스의 상태변화 • 18. SIGCONT(CONT) : STOP 시그널 이후 계속 진행할 때 사용 • 19. SIGSTOP(STOP) : 정지. 이 시그널 역시 잡을 수 없다. • 20. SIGTSTP(TSTP) : 키보드에 의해 발생하는 시그널로 Ctrl+Z로 생성된다.

  7. kill 시스템 콜 : Sending Signals void fork12() { pid_tpid[N]; inti, child_status; for (i = 0; i < N; i++) if ((pid[i] = fork()) == 0) while(1); /* Child infinite loop */ /* Parent terminates the child processes */ for (i = 0; i < N; i++) { printf("Killing process %d\n", pid[i]); kill(pid[i], SIGINT); } /* Parent reaps terminated children */ for (i = 0; i < N; i++) { pid_twpid = wait(&child_status); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status)); else printf("Child %d terminated abnormally\n", wpid); } }

  8. 부모보다 먼저(아무 말없이) 종료되어 status가 전달되지 않아서, 자식프로세스를 reaping 하지 못하는 경우 발생. -  자식 process를기다려주거나 SIGNAL을이용하여 처리한다. ! Zombie 만들기 : //부모는 종료했으나, 죽지 않는 child, 이 child는 어떻게 될가요? void fork8() { if (fork() == 0) { /* Child */ printf("Running Child, PID = %d\n",getpid()); while (1) ; /* Infinite loop */ } else { printf("Terminating Parent, PID = %d\n",getpid()); exit(0); } } 자식 프로세스는 종료되면서 성공적인 종료를 알리기 위해 0 값을 커널에리턴합니다. 그러나, 이 때, 커널은 자식 프로세스를 바로 종료시키지 않고, 부모 프로세스에게 자식이 죽으며 전해준 값(0)이 전달될 때까지 기다려줘요. 자식의 상태정보값은 부모 프로세스가 커널에게 요청할 때에만 전달됩니다. 부모가 요청없이 종료했으므로 자식의 신호는 부모에게 전달될 수 없고, 이 때 자식은 작업은 종료했으나 메모리는 남아있는 zombie 상태가 됩니다. // 부모는 종료되기 전, 종료하는 child - zombie가 되죠. void fork7() { if (fork() == 0) { /* Child */ printf("Terminating Child, PID = %d\n", getpid()); exit(0); } else { printf("Running Parent, PID = %d\n", getpid()); while(1) //do something ; /* Infinite loop */ } }

  9. 앞 페이지의 두 예제 소스를 보면 부모와 자식간 오고 가는 대화가 없어도 너무 없어요. 자식이 무엇을 하는지 말든지에관심없이 자기일 끝났다고 그냥 종료하는 부모와.. -> 자식은 ppid()부모를 잃고 떠돌다가 init의 자식으로 들어가죠 부모가 있는 자식이되 일련의 허락없이(제멋대로) 종료해버리는 자식이 있죠. 무릇, 참된 부모는.. 자식이 어떤 상황에 놓여있는지 파악해야 하며 자식을 기다릴 줄 알아야 하고 무릇, 자식이라면 자신의 현재 상황을 부모에게 알려주어야 하겠습니다. 부모에게는 기다림을 권고하고 자식의 학교생활이 궁금할 때 선생님의 도움을 받아 자식 프로세스의 상황을 알아볼 수 있듯이 시스템의 도움을 받습니다.  system call ( C 라이브러리 함수가 아니에요 !) wait() 와signal()

  10. 모르는 명령어가 있다면 무작정 모른다. 버티지 말고 # man2 wait를 실행해보도록.! wait() 시스템 콜 • * fork를 사용하여 child process를 생성하는 경우 parent process는 child process를 wait하여 child process가 zombie가 되는 것을 막아야 한다. • 자식 프로세스가 종료되면, 리눅스커널은 그것의 메모리를 해제하고 파일을 닫는다. 종료상태는 프로세스의 프로세스 테이블에 저장된다. • but, 부모프로세스가 자식프로세스의 종료에 대한 관심없이 계속 동작을 수행하는 동안 하나 이상의 이유로 자식프로세스가 종료됐을때, 부모프로세스가 이 정보를 가져갈 때까지의 상태에 있는 자식프로세스를 좀비라고 한다. (Reaping되지 않은) • 일반적으로는 SIGCHLD 처리 함수안에서wait, waitpid함수를 사용하여 child process가 zombie가 되는 것을 막는다. • wait(), waitpid() : process의 종료나 signal함수호출신호를 기다리는 경우 • 호출한 영역에서 일시중지 • pause() : signal을 기다리는 경우

  11. #man 사용법 보는 방법 • # manman : man 명령어에 대한 manual. • The table below shows the section numbers of the manual followed by the types of pages they contain. • 1 Executable programs or shell commands • 2 System calls (functions provided by the kernel) • 3 Library calls (functions within program libraries) • 4 Special files (usually found in /dev) • 5 File formats and conventions eg /etc/passwd • 6 Games • 7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) • 8 System administration commands (usually only for root) • 9 Kernel routines [Non standard] • 따라서 쉘명령어wait에 대한 manual • # man 1 wait • 시스템 콜 wait에 대한 manual • # man 2 wait

  12. wait(), waitpid()함수를 통해 알 수 있는 child 정보 (앞으로는 헤매지만 말고 스스로 찾아보세요….!!!!!!!!!!) 상태정보를 담아오기 위한 그릇. 주소! 를보내야 겠죠? pid_t wait(int *status) pid_twaitpid(pid_tpid, int *status, int options); (#man 2 wait 중 .) wait 함수 : 자식이 종료될 때까지, 또는 현재 프로세스를 종료시키거나 시그널 처리 함수를 호출하는 행동을 하는 신호가 전달될 때까지 현재 프로세스의 실행을 일시 중지시킨다. 만일 자식이 호출 시간에 이미 종료되었다면(좀비 프로세스), 함수는 즉시 리턴한다. 자식이 사용한 시스템 자원들은 모두 풀어진다. waitpid함수 : pid인자가 가리키는 자식이 종료될 때 까지, 또는 현재 프로세스를 종료시키거나 시그널 처리 함수를 호출하는 행동을 하는 신호가 전달될 때까지 현재 프로세스의 실행을 일시 중지시킨다. 만일 pid로 지정된 자식이 호출 시간에 이미 종료되었다면(좀비 프로세스), 함수는 즉시 리턴한다. status, 와 option ( 뒷장)

  13. pid_t wait(int *status) pid_twaitpid(pid_tpid, int *status, int options); • … (이어서 ) • 리턴되는pid 값은 다음중 하나이다. • < -1 : 프로세스 그룹 ID가 pid의 절대 값과 같은 어떤 자식 프로세스를 기다리라는 의미이다. • -1 : 어떤 자식 프로세스를 기다리라는 의미이다; 이것은 wait 에서 나타난 것과 같은 행동을 한다. • 0 : 프로세스 그룹 ID가 호출 프로세스의 ID와 같은 어떤 자식 프로세스를 기다리라는 의미이다. • > 0 : 프로세스 ID가 pid의 값과 같은 자식을 기다리라는 의미이다. • options 의 값은 0 이거나 다음 상수의 어떤 것과 OR 이다. • WNOHANG : 이것은 어떤 자식도 종료되지 않았다면 즉시 리턴하라는 의미이다. • WUNTRACED : 이것은 멈추거나 상태가 보고되지 않은 자식들을 위해 역시 리턴하라는 의미이다. 만일 status 가 NULL이 아니라면wait 또는 waitpid는 status가 가리키는 위치에 상태 정보를 저장한다. 이 상태는 다음 매크로들로 평가된다.(이들 매크로는 인자로써 stat 버퍼(int값!)를 가지고 있다. -- 버퍼에 대한 포인터가 아니다!) • WIFEXITED(status) : 자식이 정상적으로 종료되었다면 non-zero 이다. • WEXITSTATUS(status) : exit() 를 호출하기 위한 인자나 주 프로그램에서 return 문장을 위한 인자로써 설정되고 종료된 자식의 반환 코드의 최하위 8비트를 평가한다. 이 매크로는 WIFEXITED 가 non-zero 를 반환할 때만 평가된다. • WIFSIGNALED(status) : 만일 자식 프로세스가 잡혀지지 않은 신호때문에 종료되었다면 참을 반환한다. • WTERMSIG(status) : 자식 프로세스를 종료하도록 야기한 신호의 숫자를 반환한다. 이 매크로는 만일 WIFSIGNALED 가 non-zero 를 반환할 경우만 평가된다. • WIFSTOPPED(status) : 반환의 원인이 된 자식 프로세스가 현재 정지되어 있다면 참을 반환한다.; 이것은 이 함수가 WUNTRACED를 사용했을 때만 가능하다. • WSTOPSIG(status) : 자식을 정지하도록 야기한 신호의 숫자를 반환한다. 이 매크로는 WIFSTOPPED 가 non-zero 를 반환할 경우만 평가된다.

  14. 이제 wait( )를 적용해 봅시다. (1): int wait(int *child_status). // 부모는 종료했으나, 죽지 않는 child, 이 child는 어떻게 될가요? void fork8() { inti = 0; if (fork() == 0) { /* Child */ printf("Running Child, PID = %d\n",getpid()); while (i < 20) printf(“I want to play~!”); } else { printf("Terminating Parent, PID = %d\n", getpid()); exit(0); } } 무한루프를 마냥 기다릴 수는 없으므로 변경 여기서, 자식이 종료되기를 wait.! //자식이 종료되기를 기다렸다가 부모도 종료합니다. void fork8-1() { intstatus; if (fork() == 0) { /* Child */ printf("Running Child, PID = %d\n",getpid()); while (i < 20) printf(“[%d] : I want to play~! \n”, i); } else { printf(“Good Parent, PID = %d\n", getpid()); wait(&status);printf(“Terminating.! \n”); exit(0); //이 라인이 없어도 종료는 됩니다. } }

  15. 이제 wait( )를 적용해 봅시다. (2): int wait(int *child_status). parent[0]:11136 parent[1]:11136 parent[2]:11136 parent[3]:11136 parent[4]:11136 child : 11137 child : 11139 child : 11141 Child 11137 terminated with exit status 100 Child 11139 terminated with exit status 102 Child 11141 terminated with exit status 104 child : 11138 Child 11138 terminated with exit status 101 child : 11140 Child 11140 terminated with exit status 103 #define N 5 int main() { pid_tpid[N]; // 여러 개의 자식을 만들어 pid를 저장하기 위한 배열. int i, child_status; for (i = 0; i < N; i++){ if ((pid[i] = fork()) == 0){ sleep(1); printf("child : %d \n", getpid()); exit(100+i); /* Child가 종료되면서 100+i 를 들고갑니다. } else printf("parent[%d]:%d \n", i, getpid()); } for (i = 0; i < N; i++) { wpid = wait(&child_status); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status)); else printf("Child %d terminate abnormally\n", wpid); } }

  16. wait() 로는 부족한 일 • 언제 자식 프로세스가 종료될 것인지를 커널이 예측할 수 있을가? • 무작정 기다리말고, 자식 프로세스가 종료되는 순간에 • 커널이부모 프로세스에게 자식 프로세스가 종료됨을 알려주도록 하자! • 시그널 핸들링 개념의 동기 : code 에 여러 시그널 핸들러를 설치하여 테스트해 봅니다. • 시그널이 발생했을 때, 미리 준비해 놓은 함수가 호출되도록 연결해주는 작업 • signal 함수 / sigaction함수를 통한 핸들링 • (sigaction함수가 시스템 입장에서는 보다 안정적.)

  17. 이제 Signal을 받아 처리해봅시다.SIGNAL 과 Handler 의 간단한 예 : • // 부모와 자식 둘 다 무한 루프 상태, wait()는적합하지 않아요. Why?! • // signal을 이용하여 어떤 처리를 할 수 있을까. • // 일단, 백그라운드 동작 상태, 혹은 다른 쉘에서SIGNAL을 보내주어야 합니다.// 1. kill -9 를 이용하여 각각의 프로세스를 강제종료가 가능하다. 단 자식먼저. • // 2. SIGNALhandler를 설치하여 처리한다. // 또는 , 소스 내부에서 kill() 함수를 통해 SIGNAL을 전달해야 합니다.(slide 18, 22) #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <signal.h> void handler1(int sig) { printf(” process(%d)에 signal[%d]이 전달됨 \n”, getpid(), sig); // exit(0);  이 부분을 주석처리 할 때와 하지 않을 때의 차이를 알 수 있겠지요? } intmain() { pid_tpid, ppid; signal(SIGINT, handler1); //SIGINT가 들어오면 handler를 호출 signal(SIGCHLD, handler1); //SIGCHLD 가 들어오면 handler를 호출 , handler2를 만들어 호출할 수도 있겠죠? // ….. if (fork() == 0) { printf("Running Child, PID = %d\n", getpid()); while(1) ; //무한루프 } else { printf("Running Parent, PID = %d\n", getpid()); while(1) ; //무한루프 } }

  18. 이제 wait()와 SIGNAL()을 적용해 봅시다. • int main() • { • intpid; • int status; • intspid; • int i; • // SIGCHLD에 대해서 시그널핸들러를 설치한다. • signal(SIGCHLD, zombie_handler); • for (i = 0; i < 3; i++) • { • pid = fork(); • intrandom_value = (random()%5)+3; • if (pid == 0) • { • // 랜덤 값을 이용하여 기다린 후 종료한다. • printf("I will be back %d %d\n", random_value, getpid()); • sleep(random_value); • return random_value; • } • } • // (동기함수) 키보드 대기, (모든자식이 죽을 때 즈음 키 입력)getchar(); // 너무 빨리 치면 어떤 상황이 올까요? • printf("종료합니다.\n\n"); • } #include <unistd.h> #include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> void zombie_handler() { int status; intspid; spid = wait(&status); printf("자식프로세스 wait 성공 \n"); printf("========================\n"); printf("PID : %d\n", spid); printf("Exit Value : %d\n", WEXITSTATUS(status)); printf("Exit Stat : %d\n", WIFEXITED(status)); }

  19. wait(&status) 만으로도 상태정보를 읽어와 해석할 수 있는데 waitpid()는 왜 사용할까요? 자식이 여러 개인 경우라면 wait() 로는 곤란하겠죠? 이미종료했는데 마냥 임의의자식을 wait()하라고 하면 이제 blocking상태에 이릅니다. waitpid()의적용예는 여러분이 조사해보도록 하세요. (중간/기말에 반영하도록 하겠습니다.)

  20. 이제 다양한 SIGNAL을 보내봅니다. SIGSEGV 유발하는scanf.c [root@localhost test]# ./scanf scanf명령 중 SIGSEGV, SIGABRT 1346798abcdefgad;kja;dksfja;kdsfadsfsdafadsfsdfadsfasdfasdf str = % Error : Segmentation Fault !! [root@localhost test]# ^C void handler(int sig) { printf(” process(%d)에 signal[%d]이 전달됨 \n”, getpid(), sig); exit(0); } intmain() { int i=0; inta[5]={0}; char str[5]; printf("scanf명령 중 SIGSEGV, SIGABRT \n"); signal(SIGSEGV, handler); signal(SIGABRT, handler); while(1) { scanf("%s", str); printf("str = %s \n", str); a[i] = i; printf("a[%d] = %d \n", i, i); i++; } }

  21. Kill()를 통해 Signal을보내봅니다. • void int_handler(int sig) { • printf("Process %d received signal %d\n", getpid(), sig); • exit(0); • } • void fork13() { • pid_tpid[N]; • int i, child_status; • signal(SIGINT, int_handler); • for (i = 0; i < N; i++) { • if ((pid[i] = fork()) == 0) while(1) ; /* child infinite loop • } • for (i = 0; i < N; i++) { • printf("Killing process %d\n", pid[i]); • kill(pid[i], SIGINT); • } • for (i = 0; i < N; i++) { • pid_twpid = wait(&child_status); • if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", , WEXITSTATUS(child_status)); • else printf("Child %d terminated abnormally\n", wpid); • } • } # ./forks Killing process 25417 Killing process 25418 Killing process 25419 Killing process 25420 Killing process 25421 Process 25417 received signal 2 Process 25418 received signal 2 Process 25420 received signal 2 Process 25421 received signal 2 Process 25419 received signal 2 Child 25417 terminated with exit status 0 Child 25418 terminated with exit status 0 Child 25420 terminated with exit status 0 Child 25419 terminated with exit status 0 Child 25421 terminated with exit status 0 #

  22. Internal Signal 의예 : Alarm (동기식signal) • int main() { • printf(" alarm(0) 일 때 종료"); • signal(SIGALRM, handler); • alarm(2); /* send SIGALRM in 2 second */ • while (1) { • sleep(1); • printf(". Beeps : %d \n“,beeps); • if(beeps > 3) alarm(0); // • /* handler returns here */ • } • } /* * internal.c - A program that responds to interally generated events (SIGALARM signals) */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> int beeps = 0; /* SIGALRM handler */ void handler(int sig) { printf("BEEP\n"); fflush(stdout); if (++beeps < 10)  beeps < 2 로바꾸면? alarm(2); //2초마다 SIGALRM 전송 else { printf("BOOM!\n"); exit(0); } }

  23. External Signal : (비동기식signal) • int main() { • printf(" backround수행후ctrl+c또는 kill -SIGINT pid로 SIGINT를 전송\n"); • signal(SIGINT, handler); /* installs ctl-c handler */ • while(1) { • } • } [root@localhost test]# ./external & [root@localhost test]# ps PID TTY TIME CMD 10907 pts/12 00:00:00 bash 11217 pts/12 00:00:03 external 11223 pts/12 00:00:00 ps [root@localhost test]# kill -2 11217 [root@localhost test]# You think hitting ctrl-c will stop the bomb? kill -2 11217Well...OK [root@localhost test]# kill -2 11217 [root@localhost test]# You think hitting ctrl-c will stop the bomb? Well...OK [root@localhost test]# fg ./external ^CYou think hitting ctrl-c will stop the bomb? ^CWell...OK You think hitting ctrl-c will stop the bomb? ^CWell...OK You think hitting ctrl-c will stop the bomb? Well... /* * external.c - A program that responds to externally * generated events (ctrl-c) */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> void handler(int sig) { printf("You think hitting ctrl-c will stop the bomb?\n"); sleep(2); printf("Well..."); fflush(stdout); printf("OK\n"); // exit(0); 여러 번의 시그널을 받아보기 위해서 주석처리하고 수행해 보세요. }

  24. 시스템 콜 함수에 대해서는 더 조사해 보세요 • http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Assembly/Documents/article_linux_systemcall_quick_reference • 파일 및 파이프 • open(), read(), write(), close() … • seek(), fstat(); .. • popen() //process의 stdout을 파일로 받는다. • chmod(), chown(); • pipe() … • Proccess제어 • fork(), getpid(), kill(), signal(), semaphore() 등 • 기타 • 공유메모리관련 : shmget() • 시스템 시간 : time() • … • (Non-Logical Jump 는 skip합니다.) 수고했습니다.!!!

  25. SIGNAL 읽어보기 : • 기본 1 : 시그널 처리기 • http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/Signal/SignalHow • 기본 2 : 시그널 처리기 • http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/Signal/SignalHow2 • sigaction: 좀더 잘 처리하기 • http://www.joinc.co.kr/modules/moniwiki/wiki.php/man/2/sigaction?cx=002661009167463862046%3A8oq6cxlfibu&cof=FORID%3A9&q=sigaction&sa=Search&ie=EUC-KR#1257

  26. A,B반 Q&A Q1) 기본이해는 쉬운데 시험문제가 과제, 응용이 어렵습니다 • 매무 평이한 질문이면서 또, 매우 심각한 질문이기도 합니다. 진정 ‘기본’을 이해할 수 있었다면 이제 다음으로 진행할 수 있어야 합니다. • 예를 들어 ‘숫자’를 알고 ‘더하기’의 의미를 이해했다면 , 그리고 • 1+2, 3+4, 5+6을 연습했다면 8+9 도, 21+34에 대해서도 계산할 수 있어야 합니다. 다음으로 진행하기가 힘들다면.., 지금 내가 ‘기본’을 이해하고 있는 것이 사실인가? 이해했다고 믿는 것은 아닌가? 에 대해 한번쯤 의문을 가져야 하겠습니다. 그 후, 다시 개념의 추상화  구체화 하여 이해하려는 시도가 있어야 하겠습니다.

  27. Q2) 부모프로세스가 죽을 때 자식프로세스가 같이 죽는게 맞나요? 일반적으로는, 부모가 정상종료/비정상종료 할 때, 멀쩡히 살아있는 자식을 데려가 함께 죽여버리지는 않습니다. Reaping. 즉자식이 사용하던 자원을 거두어주는 역할을 해야하므로 먼저 죽는 일은 없도록 해야 합니다.! (일부러 죽는 경우는 있습니다만, 그전에 어떠한 처리가 필요한 거죠) 그래서 부모는 자식이 살아있는 한 죽지않도록waiting 을 해주어야 하고 자식이 최소한 죽었는지 살았는지의 signal을 요청하여 catch해야 합니다. 슬라이드 앞장부터 큰 제목을 위주고 다시 읽어본 후, 소스를 분석해보도록 하세요.

  28. Q3) fork()는 어떤 프로그램 만들 때 자주 쓰이나요? • 흔히.. 할 일은 많은데 시간은 제한되어있고 몸은 하나밖에 없어서 아쉬울 때가 많습니다. 몸이 하나만 더 있었다면작업에 대한 역할을 분담할 수 있을 겁니다. 크게 말하면 fork()는 작업의 역할을분담할 수 있도록 별도의 process를생성하는 거죠. (반면, Thread는 한 프로세스 내에서의 작업을 분담하여 같이 한다는 의미가 더 큽니다.) 흔히 요즘의 프로그램들은 ‘다중xx시스템’ ‘멀티xx시스템’이라는 타이틀이 많이 붙어요.연습문제 수준을 벗어나면, 무조건 돌아가게만 만드는 프로그램이 아니라, 복잡한작업네트웍상에서여러 개의 프로그램이 서로 잘 동작하도록 하려면 새로운 일꾼도 필요합니다. 시스템 서버와 협력하여 일련의 signal도 송수신 해주어야 할 것입니다. 내년에 많이 쓰게 되겠죠? ^^ Q4) fork(),sigaction() 등의 함수에 대한 사용법을 모르겠습니다. 인자와 예제설명이 필요합니다. • 음…요런 내용은..사탕 줄 테니까 개별 방문 하세요.!!

More Related