제9장 프로세스 제어

Similar documents
chap12(process).hwp

<C1A63130C0E5C7C1B7CEBCBCBDBA2E687770>

<4D F736F F F696E74202D FC7C1B7CEBCBCBDBA20BBFDBCBAB0FA20BDC7C7E0205BC8A3C8AF20B8F0B5E55D>

2009년 상반기 사업계획

제1장 Unix란 무엇인가?

좀비프로세스 2

ABC 11장

10.

Microsoft PowerPoint - chap9 [호환 모드]

6주차.key

Microsoft PowerPoint - 10_Process

1장. 유닉스 시스템 프로그래밍 개요

제12장 파일 입출력

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

제1장 Unix란 무엇인가?

Microsoft PowerPoint - 09-Pipe

리눅스 프로세스 관리

Microsoft PowerPoint - ch09_파이프 [호환 모드]

2009년 상반기 사업계획

제8장 프로세스

/chroot/lib/ /chroot/etc/

Microsoft PowerPoint - Lecture_Note_7.ppt [Compatibility Mode]

제8장 프로세스

chap7.key

2009년 상반기 사업계획

슬라이드 1

vi 사용법

System Programming Lab

제1장 Unix란 무엇인가?

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

슬라이드 1

PowerPoint 프레젠테이션

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

슬라이드 1

고급 프로그래밍 설계

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

PowerPoint 프레젠테이션

슬라이드 1

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

untitled

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

<4D F736F F F696E74202D FB8DEB8F0B8AE20B8C5C7CE205BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - [2009] 02.pptx

untitled

PowerPoint 프레젠테이션

2009년 상반기 사업계획


Microsoft PowerPoint - SP6장-시그널.ppt [호환 모드]

Microsoft PowerPoint oshw1&2.ppt [호환 모드]

제1장 Unix란 무엇인가?

1장. 유닉스 시스템 프로그래밍 개요

The Pocket Guide to TCP/IP Sockets: C Version

Microsoft PowerPoint oshw1.ppt [호환 모드]

Microsoft PowerPoint UNIX Shell.ppt

11장 포인터

PowerPoint 프레젠테이션

Microsoft PowerPoint - ch10 - 이진트리, AVL 트리, 트리 응용 pm0600

금오공대 컴퓨터공학전공 강의자료

<4D F736F F F696E74202D BDC3B1D7B3CEB0FA20BDC3B1D7B3CE20C3B3B8AE2E707074>

3. 다음장에나오는 sigprocmask 함수의설명을참고하여다음프로그램의출력물과그출력물이화면이표시되는시점을예측하세요. ( 힌트 : 각줄이표시되는시점은다음 4 가지중하나. (1) 프로그램수행직후, (2) kill 명령실행직후, (3) 15 #include <signal.

Microsoft PowerPoint oshw1.ppt [호환 모드]

C++ Programming

untitled

본 강의에 들어가기 전

Microsoft PowerPoint APUE(Intro).ppt

슬라이드 1

고급 IPC 설비

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

Chapter #01 Subject

본 강의에 들어가기 전

Microsoft PowerPoint - 10_Signal

Microsoft PowerPoint UNIX Shell.pptx

歯9장.PDF

À©µµ³×Æ®¿÷ÇÁ·Î±×·¡¹Ö4Àå_ÃÖÁ¾

3. 다음장에나오는 sigprocmask 함수의설명을참고하여다음프로그램의출력물과그출력물이화면이표시되는시점을예측하세요. ( 힌트 : 각줄이표시되는시점은다음 6 가지중하나. (1) 프로그램수행직후, (2) 5 초후 (3) 10 초후 (4) 15 #include <signa

제 14 장포인터활용 유준범 (JUNBEOM YOO) Ver 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다.

PowerPoint 프레젠테이션

학번 : 이름 1. 다음프로그램실행결과를예측하시오. $./a.out & [1] 7216 $ kill -USR $ kill -USR 아래학생이작성한쓰레드코드의문제점을설명하시오. void* thread_main() { pthread_mutex_t

PowerPoint 프레젠테이션

<4D F736F F F696E74202D20BFEEBFB5C3BCC1A6BDC7BDC D31C7D0B1E229202D20BDA92E BC8A3C8AF20B8F0B5E55D>

이번장에서학습할내용 동적메모리란? malloc() 와 calloc() 연결리스트 파일을이용하면보다많은데이터를유용하고지속적으로사용및관리할수있습니다. 2

PowerPoint 프레젠테이션

Microsoft PowerPoint - chap06-2pointer.ppt

BMP 파일 처리

fprintf(fp, "clf; clear; clc; \n"); fprintf(fp, "x = linspace(0, %d, %d)\n ", L, N); fprintf(fp, "U = [ "); for (i = 0; i <= (N - 1) ; i++) for (j = 0

PowerPoint 프레젠테이션

11장 포인터

Microsoft PowerPoint - chap4 [호환 모드]

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

Microsoft PowerPoint - Lecture_Note_5.ppt [Compatibility Mode]

Microsoft PowerPoint - chap12-고급기능.pptx

The Pocket Guide to TCP/IP Sockets: C Version

The Pocket Guide to TCP/IP Sockets: C Version

Microsoft PowerPoint - chap10-함수의활용.pptx

02장.배열과 클래스

Microsoft PowerPoint - C++ 5 .pptx

ch15

교육지원 IT시스템 선진화

설계란 무엇인가?

PowerPoint 프레젠테이션

Transcription:

제 9 장프로세스제어 리눅스시스템프로그래밍 청주대학교전자공학과 한철수

제 9 장 목차 프로세스생성 프로그램실행 입출력재지정 프로세스그룹 시스템부팅 2

9.1 절 프로세스생성 fork() 시스템호출 새로운프로그램을실행하기위해서는먼저새로운프로세스를생성해야하는데, fork() 시스템호출이새로운프로세스를생성하는유일한방법임. 함수프로토타입 pid_t fork(void); 새로운자식프로세스를생성함. 자식프로세스에서는 0 을반환하고, 부모프로세스에서는자식프로세스의 PID 를반환함. ( 매우중요 ) 3

9.1 절 fork() 시스템호출실행전과후 fork() 시스템호출은부모프로세스를똑같이복제하여자식프로세스를생성함. 자기복제 fork() 시스템호출이실행되면자식프로세스가즉시생성됨. 그후, 부모프로세스와자식프로세스는각각독립적으로실행을계속함. PC (Program Counter): 다음에실행될명령어의주소를가지고있는레지스터로서, 명령어포인터라고도함. 4

9.1 절 fork1.c (p.276) #include <stdio.h> #include <unistd.h> int main() { int pid; printf("[%d] 프로세스시작 \n", getpid()); pid = fork(); printf("[%d] 프로세스 : 반환값 %d\n", getpid(), pid); 부모프로세스가실행. 부모프로세스가실행. 자식프로세스가실행. 5

9.1 절 for() 시스템호출의반환값처리 fork() 시스템호출후에실행되는코드들은부모프로세스와자식프로세스에서모두실행됨. 그러면부모프로세스와자식프로세스가서로다른일을하게하려면어떻게해야할까요? 반환값을이용함. 왜냐하면 fork() 시스템호출은자식프로세스에서는 0 을반환하고, 부모프로세스에서는자식프로세스의 PID 를반환하기때문에. 서로다른일을하도록처리하는코드 pid = fork(); if( pid == 0 ) { 자식프로세스가실행할코드 ; else { 부모프로세스가실행할코드 ; 6

9.1 절 fork2.c (p.277) #include <stdio.h> #include <unistd.h> int main() { int pid; pid = fork(); if(pid==0) { printf("[child] : Hello, world pid=%d\n", getpid()); else { printf("[parent] : Hello, world pid=%d\n", getpid()); 자식프로세스가실행. 부모프로세스가실행. 7

9.1 절 fork3.c (p.278) #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { int pid1, pid2; pid1 = fork(); if(pid1==0) { printf("[child 1] : Hello, world! pid=%d\n", getpid()); exit(0); pid2 = fork(); if(pid2==0) { printf("[child 2] : Hello, world! pid=%d\n", getpid()); exit(0); 첫번째자식프로세스가종료됨. 두번째자식프로세스가종료됨. 8

9.1 절 wait() 시스템호출 부모프로세스는 wait() 시스템호출을실행하여자식프로세스중의하나가종료될때까지기다릴수있음. wait() 부모프로세스 fork() 자식프로세스 exit() 함수프로토타입 pid_t wait(int *status); 실행하면자식프로세스중하나가종료될때까지기다림. 자식프로세스가종료될때의종료코드가 *status 에저장됨. 종료된자식프로세스의 PID 를반환함. 9

9.1 절 forkwait.c (p.280) #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { int pid, child, status; printf("[%d] 부모프로세스시작 \n", getpid()); pid = fork(); if(pid == 0) { printf("[%d] 자식프로세스시작 \n", getpid()); exit(1); child = wait(&status); printf("[%d] 자식프로세스 %d 종료 \n", getpid(), child); printf("\t 종료코드 %d\n", status>>8); 자식프로세스가종료됨. 종료코드 : 1 자식프로세스가종료되기를기다림. 10

9.1 절 waitpid() 시스템호출 부모프로세스는 waitpid() 시스템호출을실행하여자식프로세스중하나를지정하여그것이종료될때까지기다릴수있음. 함수프로토타입 pid_t waitpid(pid_t pid, int *status, int options); PID 가 pid 인자식프로세스가종료될때까지기다림. 자식프로세스가종료될때의종료코드가 *status 에저장됨. options 는부모프로세스의대기방법을나타내며보통 0 을사용함. 종료된자식프로세스의 PID 를반환함. 11

9.1 절 waitpid.c (p.282) #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { int pid1, pid2, child, status; printf("[%d] 부모프로세스시작 \n", getpid( )); pid1 = fork(); if(pid1 == 0) { printf("[%d] 자식프로세스 [1] 시작 \n", getpid( )); sleep(1); printf("[%d] 자식프로세스 [1] 종료 \n", getpid( )); exit(1); pid2 = fork(); if(pid2 == 0) { printf("[%d] 자식프로세스 #2 시작 \n", getpid( )); sleep(2); printf("[%d] 자식프로세스 #2 종료 \n", getpid( )); exit(2); child = waitpid(pid1, &status, 0); printf("[%d] 자식프로세스 #1 %d 종료 \n", getpid( ), child); printf("\t종료코드 %d\n", status>>8); 12

9.2 절 프로그램실행 부모프로세스가 fork() 시스템호출을통해자식프로세스를생성하면, 자식프로세스는부모프로세스와동일한코드를실행함. 부모프로세스와자식프로세스에서 fork() 시스템호출의반환값이서로다르다는점을이용하여, 부모프로세스와자식프로세스가서로다른일을하도록하였음. 그러면자식프로세스에게새로운프로그램을실행시키기위해서는어떻게해야할까요? exec() 시스템호출을실행하여프로세스는새로운프로그램을실행시킬수있음. 13

9.2 절 exec() 시스템호출실행전과후 프로세스가 exec() 시스템호출을실행하면, 그프로세스내의프로세스이미지 ( 코드, 데이터, 힙, 스택등 ) 는새로운프로세스이미지로대치됨 ( 바뀜 ). 자기대치 단, PID 는바뀌지않음. PC (Program Counter): 다음에실행될명령어의주소를가지고있는레지스터로서, 명령어포인터라고도함. 14

9.2 절 exec() 시스템호출의사용예 exec() 시스템호출이성공하면기존프로세스이미지는새로운프로세스이미지로대치됨. exec() 시스템호출이성공한경우에는반환값이반환되지않고, 실패한경우에만반환값이반환됨. fork() 시스템호출을실행한후에 exec() 시스템호출을실행하는것이일반적임. if((pid=fork())==0){ exec(arguments); exit(1); // 부모프로세스는아래를계속실행 자식프로세스에게실행시킬프로그램을 arguments 로전달함. exec() 시스템호출이실패한경우에만실행됨. 15

9.2 절 exec() 시스템호출 함수프로토타입 int execl(char* path, char* arg0, char* arg1,..., NULL); int execv(char* path, char* argv[ ]); int execlp(char* file, char* arg0, char* arg1,..., NULL); int execvp(char* file, char* argv[ ]); 프로세스이미지를 path( 또는 file) 가가리키는새로운프로그램의프로세스이미지로대치한후새코드를실행함. exec( ) 시스템호출이성공하면반환값을반환하지않고, 실패하면 -1 을반환함. 실행예 execl("/bin/echo", "echo", "hello", NULL); execv(argv[1], &argv[1]); 16

9.2 절 execute1.c (p.286) #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main( ) { printf(" 부모프로세스시작 \n"); if(fork( ) == 0) { execl("/bin/echo", "echo", "hello", NULL); fprintf(stderr," 첫번째실패 "); exit(1); printf(" 부모프로세스끝 \n"); 자식프로세스의프로그램이 echo hello 로교체됨. exec() 가실패한경우에만실행됨. 17

9.2 절 execute2.c (p.287) #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { printf(" 부모프로세스시작 \n"); if(fork() == 0) { execl("/bin/echo", "echo", "hello", NULL); fprintf(stderr," 첫번째실패 "); exit(1); if(fork() == 0) { execl("/bin/date", "date", NULL); fprintf(stderr," 두번째실패 "); exit(2); if(fork() == 0) { execl("/bin/ls","ls", "-l", NULL); fprintf(stderr," 세번째실패 "); exit(3); printf(" 부모프로세스끝 \n"); 18

9.2 절 execute3.c (p.288) #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { int child, pid, status; pid = fork( ); if(pid == 0) { execvp(argv[1], &argv[1]); fprintf(stderr, "%s: 실행불가 \n",argv[1]); else { child = wait(&status); printf("[%d] 자식프로세스 %d 종료 \n", getpid(), pid); printf("\t 종료코드 %d \n", status>>8); 19

질문 Q&A 20

9.2 절 system() 함수 system() 함수는 C 라이브러리함수임. system() 함수는자식프로세스를생성하고자식프로세스로하여금명령어를실행시키는것을한번에수행해줌. system() 함수는지금까지다룬 fork(), exec(), waitpid() 시스템호출을이용하여구현되었음. 함수프로토타입 int system(const char *cmdstring); 이함수는 /bin/sh c cmdstring 를호출하여 cmdstring 에지정된명령어를실행함. 명령어가끝난후, 명령어의종료코드를반환함. 사용예 system("ls -asl"); 21

9.2 절 system() 함수의구현 (p.290) #include <sys/wait.h> #include <errno.h> #include <unistd.h> int system(const char *cmdstring) { int pid, status; if(cmdstring == NULL) return 1; pid=fork(); if(pid == -1) return -1; if(pid == 0) { execl("/bin/sh", "sh", "-c", cmdstring, NULL); _exit(127); do { if(waitpid(pid, &status, 0) == -1){ if(errno!= EINTR) return -1; else return status; while(1); 명령어가없는경우 자식프로세스의생성이실패한경우 자식프로세스가 cmdstring 을실행 부모프로세스는자식프로세스가종료될때까지기다림. 인터럽트에의한에러가아니라면종료하고, 인터럽트에의한에러라면다시 waitpid() 시스템호출을실행함. 시스템호출중에러가발생되면시스템변수 errno 에는특정값이저장됨. 22

9.2 절 syscall.c (p.292) #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> int main() { int status; if((status = system("date")) < 0) perror("system() 오류 "); printf(" 종료코드 %d\n", WEXITSTATUS(status)); if((status = system("hello")) < 0) perror("system() 오류 "); printf(" 종료코드 %d\n", WEXITSTATUS(status)); system() 함수는명령어의종료코드를반환함. WEXITSTATUS(status) 는앞에서나온 status>>8 과같음. if((status = system("who; exit 44")) < 0) perror("system() 오류 "); printf(" 종료코드 %d\n", WEXITSTATUS(status)); 23

9.3 절 입출력재지정 쉘에서의입출력재지정 $ 명령어 > 텍스트파일 $ ls -l > list.txt dup() 혹은 dup2() 시스템호출을이용하여입출력재지정을구현할수있음. 함수프로토타입 int dup(int oldfd); oldfd 에대한복제본인새로운파일디스크립터를생성하여반환함. 실패하면 1 을반환함. int dup2(int oldfd, int newfd); oldfd 을 newfd 에복제하고, 복제된파일디스크립터를반환함. 실패하면 -1 을반환함. 24

9.3 절 실행예 int dup(int oldfd); int dup2(int oldfd, int newfd); 파일디스크립터 oldfd 와복제된파일디스크립터는같은파일을공유하게된다. 예 FILE *fp; fp=fopen(argv[1], w ); dup2(fp->fd, 1); puts( hello ); 1 번파일디스크립터는표준출력 (STDOUT) 의파일디스크립터임. hello 가파일에저장됨. 25

9.3 절 redirect1.c (p.294) #include <stdio.h> #include <unistd.h> int main(int argc, char* argv[]) { FILE *fp; fp=fopen(argv[1], "w"); dup2(fileno(fp), 1); fclose(fp); printf("hello stdout!\n"); fprintf(stderr, "Hello stderr!\n"); 열린파일 fp 의파일디스크립터를반환함. 파일디스크립터를표준출력 (STDOUT) 에복제함. 26

9.3 절 redirect2.c (p.295) #include <sys/wait.h> #include <stdio.h> #include <unistd.h> int main(int argc, char* argv[]) { int pid, child, status; FILE *fp; pid=fork(); if(pid==0){ fp=fopen(argv[1], "w"); dup2(fileno(fp), 1); fclose(fp); execvp(argv[2], &argv[2]); fprintf(stderr, "%s: 실행불가 \n", argv[1]); else { child=wait(&status); printf("[%d] 자식프로세스 %d 종료 \n", getpid(), child); 27

9.4 절 프로세스그룹 프로세스그룹 (process group) 은여러프로세스들의집함을의미함. 각프로세스는하나의프로세스그룹에속하게됨. 각프로세스는 PID 뿐만아니라자신이속한프로세스그룹 ID(PGID) 도가짐. 보통부모프로세스가생성하는자식프로세스들은부모와하나의프로세스그룹을생성함. 각프로세스그룹에는그그룹을만든프로세스그룹리더가있음. 프로세스그룹리더의 PID 와프로세스그룹 ID(PGID) 는같음. 프로세스 1 프로세스 2 프로세스 3 프로세스그룹 28

9.4 절 getpgrp() 시스템호출 프로세스그룹 ID(PGID) 는 getpgrp() 시스템호출을통해알수있음. 함수프로토타입 pid_t getpgrp(void); 호출한프로세스의프로세스그룹 ID 를반환함. 29

9.4 절 pgrp1.c (p.297) #include <stdio.h> #include <unistd.h> int main() { int pid; printf("[parent] PID=%d GID=%d\n", getpid(), getpgrp()); pid=fork(); if(pid==0) { printf("child: PID=%d GID=%d\n", getpid(), getpgrp()); 30

9.4 절 프로세스그룹의활용 1 프로세스그룹을이용하면그룹내의모든프로세스들을대상으로액션을취할수있음. 주로프로세스그룹내의모든프로세스들에게어떤시그널 (signal) 을보내어그룹내의모든프로세스들을제어하거나종료시킬때사용함. 예 kill -9 pid // kill pid와같음. kill -9 0 // 현재속한프로세스그룹내의모든프로세스들에게 9번시그널 (SIGKILL) 을보냄. kill -9 -pid // -는프로세스그룹을의미. 프로세스그룹 pid에있는모든프로세스들에게 9번시그널 (SIGKILL) 을보냄. 31

9.4 절 프로세스그룹의활용 2 waitpid() 시스템호출도프로세스그룹과관련이있음. pid_t waitpid(pid_t pid, int *status, int options); 첫번째인수 pid 의값에따라다양하게사용될수있음. pid == -1 임의의자식프로세스가종료하기를기다림. (wait() 시스템호출과같음.) pid > 0 PID 가 pid 인자식프로세스가종료하기를기다림. pid == 0 호출자와같은프로세스그룹내의어떤자식프로세스가종료하기를기다림. pid < -1 pid 의절대값과같은프로세스그룹내의어떤자식프로세스가종료하기를기다림. 32

9.4 절 새로운프로세스그룹만들기 setpgid() 시스템호출을통해새로운프로세스그룹을생성하거나다른프로세스그룹에멤버로들어갈수있음. 프로세스가이호출을통해새로운프로세스를생성한경우새로운그룹리더가됨. 함수프로토타입 int setpgid(pid_t pid, pid_t pgid); PID 가 pid 인프로세스의프로세스그룹 ID 를 pgid 로설정함. 성공하면 0 을, 실패하면 -1 을반환함. 예 pid == pgid PID 가 pid 인프로세스가새로운프로세스그룹의리더가됨. pid!= pgid PID 가 pid 인프로세스가프로세스그룹 ID 가 pgid 인그룹의멤버가됨. pid == 0 호출자의 PID 를사용함. pgid == 0 PID 가 pid 인프로세스가새로운프로세스그룹의리더가됨. 33

9.4 절 사용예 int setpgid(pid_t pid, pid_t pgid); 예 pid == pgid PID 가 pid 인프로세스가새로운프로세스그룹의리더가됨. pid!= pgid PID 가 pid 인프로세스가프로세스그룹 ID 가 pgid 인그룹의멤버가됨. pid == 0 호출자의 PID 를사용함. pgid == 0 PID 가 pid 인프로세스가새로운프로세스그룹의리더가됨. setpgid(getpid(), getpid()); setpgid(0, 0); 34

9.4 절 pgrp2.c (p.301) #include <stdio.h> #include <unistd.h> int main() { int pid; printf("[parent] PID=%d GID=%d\n", getpid(), getpgrp()); pid=fork(); if(pid==0) { setpgid(0, 0); printf("child: PID=%d GID=%d\n", getpid(), getpgrp()); 35

9.5 절 시스템부팅 시스템의부팅과정에서여러개의프로세스가생성되는데이과정은어떻게이루어질까? 앞에서배운 fork() 와 exec() 시스템호출을통해시스템부팅이이루어진다. 36

9.5 절 시스템부팅관련프로세스들 swapper ( 스케줄러프로세스 ) 커널내부에서만들어진프로세스로프로세스스케줄링을함. init ( 초기화프로세스 ) /etc/inittab 파일에기술된대로시스템을초기화함. getty 프로세스 로그인프롬프트를내고키보드입력을감지함. login 프로세스 사용자의로그인아이디및패스워드를검사함. shell 프로세스 시작파일을읽고실행한후에쉘프롬프트를내고사용자로부터명령어를기다림. 37

9.5 절 프로세스리스트내용확인 $ ps -ef less ps -ef grep sshd ps -ef grep mingetty 38

질문 Q&A 39