linux system programming
DESCRIPTION
Linux System Programming. Lecture #6 – 프로세스 생성과 수행. 프로세스의 소개 (1). 프로세스의 정의 : 프로세스 (Process) 란 실행중인 프로그램을 의미 예 : 파워포인터 프로그램을 실행하였을 경우 - (1) 하드디스크에 설치되어 있는 프로그램 - 저장된 프로그램 (2) 실행하기 위해 메모리에 로딩된 프로그램 - 프로세스 프로세스는 운영체제가 서비스를 제공하는 대상 - PowerPoint PPT PresentationTRANSCRIPT
Linux System Linux System ProgrammingProgramming
Lecture #6 – 프로세스 생성과 수행
Linux System Programming 2
프로세스의 소개 (1)프로세스의 소개 (1)
프로세스의 정의 : 프로세스 (Process)란 실행중인 프로그램을 의미
예 : 파워포인터 프로그램을 실행하였을 경우 -(1) 하드디스크에 설치되어 있는 프로그램 - 저장된 프로그램(2) 실행하기 위해 메모리에 로딩된 프로그램 - 프로세스
프로세스는 운영체제가 서비스를 제공하는 대상 사용자가 하나의 프로그램을 실행하면 운영체제는 그 프로그램을 실행하는 하나의 프로세스를 생성하고 , 프로세스가 프로그램을 실행하기 위해 요구하는 서비스를 제공한다
Multitasking을 지원하는 운영체제는 동시에 한 개 이상의 프로세스를 생성할 수 있으며 , 이들 프로세스가 동시에 동작하도록 서비스를 제공한다
동일한 프로그램에 대해 여러 개의 프로세스가 생성될 수 있다 예 : 동시에 파워포인터 프로그램을 2개 이상 실행한 경우
프로세스는 상호 독립적으로 동작한다
Linux System Programming 3
프로세스의 소개 (2)프로세스의 소개 (2)
프로세스의 정의 : Linux 운영체제에서 프로세스간에 계층 구조를 갖는다
Linux 운영체제에서는 fork 시스템 호출에 의하여 프로세스를 생성 프로세스 0을 제외한 모든 프로세스는 다른 프로세스가 fork 시스템 호출을 수행하여 만들어진다 .
fork를 호출한 프로세스를 부모 프로세스라 하고 , 새로 만들어진 프로세스를 자식 프로세스라 한다 .
모든 프로세스는 오직 하나의 부모 프로세스를 가질 수 있지만 , 자식 프로세스는 여러 개를 가질 수 있다 .
Linux System Programming 4
프로세스의 소개 (3)프로세스의 소개 (3)
프로세스의 정의 : Linux 커널은 각 프로세스들을 프로세스 ID( 정수값 )로
구분한다 프로세스 0은 시스템이 부트될 때 만들어지며 , 프로세스 1 을
fork 한 후에는 스와퍼 (swapper) 가 된다 프로세스 1은 init 프로세스라고 알려져 있는데 , 시스템
내의 다른 모든 프로세스의 조상이 된다
Linux System Programming 5
프로세스의 소개 (4)프로세스의 소개 (4)
프로세스의 구조 : 실행 가능 파일 (Executable File)
원시 코드 파일을 컴파일하여 생성되는 파일 구조 :
프로그램 텍스트 – 원시 코드를 컴파일하여 생성된 기계어 코드 데이터 영역 – 원시 프로그램에서 정의된 전역 변수 및 상수에 대한 정보를 저장
Linux System Programming 6
프로세스의 소개 (5)프로세스의 소개 (5)
프로세스의 구조 : 실행 가능 프로그램이 주기억 장치로 적재 (load) 되어
프로세스가 생성되면 텍스트 영역과 액티베이션 (activation) 레코드로 구분되어 존재
액티베이션 레코드는 전역 (global) 데이터 영역과 스택 영역으로 이루어져 있으며 , 전역 데이터 영역은 초기화 데이터와 비초기화 데이터 영역으로 구성
초기화 데이터 영역은 프로그램에서 초기화가 배정된 변수 , 배열이나 구조체 (structure) 등이 저장되며 , 비초기화 데이터 영역에는 초기값을 배정하지 않은 변수 , 배열 , 구조체 등의 기억 장소이다 .
Linux System Programming 7
프로세스의 소개 (6)프로세스의 소개 (6)
프로세스의 구조 : 운영 체제의 가상 공간에는 커널 프로그램이 저장된 텍스트 (te
xt) 영역과 시스템에서 수행중인 프로세스들을 관리하기 위한 프로세스 테이블들이 저장된 데이터 영역으로 구분
커널 공간에 프로세스 생성과 관련된 데이터 구조 :(1) 프로세스 테이블(2) PCB( 프로세스 제어 블록 )(3) 사용자 영역 (u-area) – 파일 디스크립터 테이블 , OS 스택 등
Linux System Programming 8
프로세스의 소개 (7)프로세스의 소개 (7)
프로세스의 구조 :
Linux System Programming 9
프로세스의 소개 (8)프로세스의 소개 (8)
프로세스의 상태 : 프로세스 문맥 (Process Context) 은 프로세스의 현재 상태를
의미 프로세스 문맥은 프로세스의 텍스트 , 전역 사용자 변수들과
데이터 구조들의 값 , 프로세스가 사용하는 기계 레지스터의 값 , 프로세스 테이블 항과 user area 에 저장된 값들 , 사용자 스택과 커널 스택의 내용 등에 의해 정의된다 .
하나의 프로세스가 실행되고 있을 때 , 시스템은 그 프로세스 문맥에서 실행 중이라고 정의
현재 CPU 가 접근하는 메모리 영역을 의미 현재 실행중인 프로세스를 중지하고 새로운 프로세스를 실행하기
위해서는 문맥 교환 (Context Switching) 이 이루어진다 실행 중인 프로세스가 시스템 호출을 요청하면 시스템은 사용자
모드에 커널 모드로 변환하여 실행중인 프로세스 문맥에서 커널 프로그램을 실행한다 (모드 변환 )
Linux System Programming 10
프로세스의 소개 (9)프로세스의 소개 (9)
프로세스의 상태 :
Linux System Programming 11
프로세스의 소개 (10)프로세스의 소개 (10)
예제 6-1: 프로세스 이미지에 대한 텍스트 (etext), 데이터 (edata), 스택
및 사용자 영역의 한계점 (end point) 을 출력해 준다 .
#define PRADDR(X) printf(" X at %o and value = %o\n",&X,X) extern etext, edata, end;static char s = 'S';int a,b = 1;
main(int argc,char *argv[]){
void sub1();static int c, d =1;char m,n = 'n';
printf("main at %o and sub1 at %o\n",main,sub1);printf("end of text segment at %o\n",&etext);
PRADDR(s); PRADDR(b);PRADDR(c); PRADDR(d);
Linux System Programming 12
프로세스의 소개 (11)프로세스의 소개 (11)
printf("end of statics & initialized externals at %o\n", &edata);
PRADDR(a);
printf("end of uninitialized externals at %o\n", &end);
PRADDR(m); PRADDR(n);PRADDR(argc); PRADDR(argv);for(b = 0; b<argc; b++)
printf("argv[%d] at %o and value = %o or %s\n", b, &argv[b], argv[b], argv[b]);
sub1(c);}
void sub1(int p){
static int t;char v;
PRADDR(t); PRADDR(p); PRADDR(v);}
Linux System Programming 13
프로세스의 크기 변경 :brk, sbrk
프로세스의 크기 변경 (1)프로세스의 크기 변경 (1)
Linux System Programming 14
프로세스의 크기 변경 :brk, sbrk
프로세스의 크기 변경 (2)프로세스의 크기 변경 (2)
Linux System Programming 15
예제 6-4: brk 와 sbrk 시스템 호출을 이용하여 수행중인 프로세스의
크기를 설정하고 출력하는 프로그램을 작성하라 .
프로세스의 크기 변경 (3)프로세스의 크기 변경 (3)
extern int etext, edata, end;main(){ int brk(), ret;
char *sbrk(), *bv;
system("clear");printf("The program text ends at %07o\n", &etext);printf("The initialized data ends at %07o\n", &edata);printf("The uninitialized data ends at %07o\n", &end);
bv = sbrk(0);printf("Current break value is %07o\n\n",bv);
ret = brk(bv+512); /* 01000 */printf("brk returned . . . . %d\n",ret);bv = sbrk(0);printf("Current break value is %07o\n\n",bv);
Linux System Programming 16
프로세스의 크기 변경 (4)프로세스의 크기 변경 (4)
ret = brk(&ret);
printf("brk returned . . . . %d\n",ret);
bv = sbrk(0);
printf("Current break value is %07o\n\n",bv);
bv = sbrk(64); /* 0100 */
printf("sbrk returned %07o\n",bv);
bv = sbrk(0);
printf("Current break value is %07o\n\n",bv);
bv = sbrk(-1024); /* memory deallocation: -02000 */
printf("sbrk returned %07o\n",bv);
printf("Current break value is %07o\n\n",bv);
}
Linux System Programming 17
프로세스의 사용자 식별 (1)프로세스의 사용자 식별 (1)
프로세스의 사용자 식별 (ID): setuid, setgid 실제 사용자 ID(Real User ID) 는 수행 중인 프로세스에 대해
책임을 지닌 사용자 ID 유효 사용자 ID(Effective User ID) 는 다음의 작업에 적용
새로 만들어진 화일의 소유권을 지정 화일 접근 허가를 검사 kill 시스템 호출에 의해 프로세스들에게 신호를 보낼 수 있는 허가를 검사
커널은 프로세스가 setuid 프로그램을 실행 (exec) 하거나 , setuid 시스템 호출을 통하여 프로세스의 유효 사용자 ID 를 변경하도록 허용한다 .
setuid 프로그램이란 허가 모드 필드의 setuid 비트가 1로 세트되어 있는 실행 가능 파일
프로세스가 setuid 프로그램을 실행 (exec) 하면 , 커널은 프로세스 테이블과 u area 상의 유효 사용자 ID 와 필드를 화일의 소유자 ID 로 세트한다
Linux System Programming 18
프로세스의 사용자 식별 (2)프로세스의 사용자 식별 (2)
프로세스의 사용자 식별 (ID):setuid, setgid
Linux System Programming 19
예제 6-2: 아래의 조건에 따라 읽기 전용 파일을 생성하는 프로그램을 작성하고
실사용자와 유효 사용자의 관계를 확인하라 .
1. 실사용자와 유효 사용자의 ID 를 출력한다 .
2. fopen() 함수를 사용하여 파일 접근의 성공과 실패를 검사한다 .
3. setuid 함수를 이용하여 실사용자와 유효 사용자가 동일하게 만든다 .
4. 1-2 를 반복한다 .
실험은 다음 단계로 한다 .
1. 프로그램을 실행하고 출력을 관측한다 .
2. 그룹 멤버가 프로그램을 수행할 수 있도록 접근 허가를 수정하여 그룹
멤버로 하여금 프로그램을 수행시킨다 .
3. set-user-id 비트를 설정하고 그룹 멤버로 하여금 프로그램을 수행시킨다 .
프로세스의 사용자 식별 (3)프로세스의 사용자 식별 (3)
Linux System Programming 20
프로세스의 사용자 식별 (4)프로세스의 사용자 식별 (4)
#include <stdio.h>
main(int argc, char *argv[]){ FILE *fp ; char line[256]; int uid; if(argc <2) { fprintf(stderr,"Usage: %s file_name\n",argv[0]); exit(1); } printf("initially uid=%d and euid%d\n",getuid(), geteuid()); fp = fopen(argv[1],"r"); if(fp = NULL) { fprintf(stderr,"first open of %s failed",argv[1]); exit(2); } else { printf("first open successful:\n"); while(fgets(fp,line,255)!=NULL) fputs(stdout,line); fclose(fp); }
Linux System Programming 21
프로세스의 사용자 식별 (5)프로세스의 사용자 식별 (5)
setuid(uid = getuid());
printf("after setuid(%d):\n uid=%d and euid=%d\n",uid, getuid(), geteuid()); fp = fopen(argv[1], "r"); if(fp == NULL) { fprintf(stderr,"second open of %s failed",argv[1]); exit(3); } else { printf("second open successful:\n"); while(fgets(line,255,fp) != NULL) fputs(line,stdout); fclose(fp); }}
Linux System Programming 22
예제 6-3:
아래 주어진 옵션 (option) 에 따라 프로세스의 정보를 출력하는
프로그램을 작성하라 . 옵션 (option) 의 분해에는 getopt
함수를 사용한다 .
-i : 사용자 (user) 와 그룹 (group) 의 실사용자 및 유효 사용자 ID
를 다음의 함수를 사용하여 출력한다 .
프로세스의 사용자 식별 (6)프로세스의 사용자 식별 (6)
Linux System Programming 23
예제 6-3: -s : setpgrp() 함수를 이용하여 프로세스를 새로운 그룹에 포함시킨다
-p : 프로세스 , 부모 프로세스 , 그룹 프로세스 ID 를 다음 함수를
이용하여 출력한다 .
-u : ulimit() 함수를 호출하여 프로세스의 크기에 대한 값을
출력한다 .
-Unewlimit: ulimit() 함수를 이용하여 프로세스 크기에 대한 값을
새로 설정한다 .
프로세스의 사용자 식별 (7)프로세스의 사용자 식별 (7)
Linux System Programming 24
프로세스의 사용자 식별 (8)프로세스의 사용자 식별 (8)
#include <stdio.h>#define GET_FSLIM 1#define SET_FSLIM 2extern char *optarg;extern int optind;
main(int argc, char *argv[]){
int getopt(), c;long ulimit(), atol();static char options[] = "ispuU:";
if(argc < 2) fprintf(stderr,"Usage: %s [-i] [-s] [-p] [-u] [-Unewulimit]\n",argv[0]);while((c=getopt(argc,argv,options)) != EOF) switch(c) { case 'i':
printf("real userid = %d\n",getuid());printf("effective userid = %d\n",geteuid());printf("real groupid = %d\n",getgid());printf("effective groupid = %d\n",getegid());break;
Linux System Programming 25
프로세스의 사용자 식별 (9)프로세스의 사용자 식별 (9)
case 's':
(void) setpgrp();
break;
case 'p':
printf("process number = %d\n",getpid());
printf("parent process number = %d\n",getppid());
printf("group process number = %d\n",getpgrp());
case 'U':
if(ulimit(SET_FSLIM,atol(optarg)) == -1)
fprintf(stderr,"Must be super-user to increase ulimit\n");
break;
case 'u':
printf("ulimit = %ld\n",ulimit(GET_FSLIM,0L));
break;
}
}
Linux System Programming 26
프로세스의 환경 변수 :getenv, putenv LINUX 프로세스의 환경은 셸 (shell) 변수들로써 이루어져 있다 . 셸 (shell) 변수들은 스택 (stack) 에 저장되어 있고 그들을 접근하는
가장 간단한 방법은 명령어 행의 인수 (argument) 들을 접근하는 것처럼 주함수 (main function) 에 파라미터를 하나 더 추가하는 것이다 .
전역 변수 envion 은 환경 변수들이 저장된 테이블의 시작 주소를 가지고 있다 . 그러므로 프로그램에서 다음과 같이 선언하여 환경 변수에 접근할 수 있다 .
프로세스의 환경변수 (1)프로세스의 환경변수 (1)
Linux System Programming 27
프로세스의 환경 변수 :getenv, putenv
프로세스의 환경변수 (2)프로세스의 환경변수 (2)
Linux System Programming 28
예제 6-5: 자신의 환경 변수들을 모두 출력하는 프로그램을 작성하라 . 환경 변수 TZ(Time Zone) 을 변경한 후 변경된 내용을 출력하여
확인하라 . 새로운 환경 변수 WARNING에 값을 설정한 후 그 내용을
출력시켜라 .
프로세스의 환경변수 (3)프로세스의 환경변수 (3)
Linux System Programming 29
프로세스의 환경변수 (4)프로세스의 환경변수 (4)
extern char **environ;
void main(int argc, char *argv[], char *envp[])
{
char *getenv();
printenv("Initially", &envp);
putenv("TZ=PST8PDT");
printenv("After changing TZ", &envp);
putenv("WARNING=Don't use envp after putenv()");
printenv("After setting a new variable",&envp);
printf("value of WARNING is %s\n",getenv("WARNING"));
}
Linux System Programming 30
프로세스의 환경변수 (5)프로세스의 환경변수 (5)
void printenv(char *label, char ***envpp)
{
char **p;
printf("---- %s ---\n",label);
printf(" envp is at %8o and contains %8o\n", envpp, *envpp);
printf("environ is at %8o and contains %8o\n", &environ, environ);
printf("My environment variables are:\n");
for(p=environ; *p; p++)
printf("(%8o) = %8o -> %s\n",p,*p,*p);
printf("(%8o) = %8o\n", p, *p);
}
Linux System Programming 31
프로세스의 생성 :fork
프로세스의 생성 (1)프로세스의 생성 (1)
Linux System Programming 32
프로세스의 생성 (2)프로세스의 생성 (2)
Linux System Programming 33
프로세스의 생성 :fork 커널은 fork 수행시 다음과 같은 순서로 동작한다 .
1. 새로운 프로세스를 위해 프로세스 테이블 항을 할당한다 . 2. 자식 프로세스에게 고유의 ID 번호를 부여한다 . 3. 부모 프로세스의 내용을 논리적으로 복사한다 . 예를 들면 , 텍스트 영역과 같은 프로세스의 일부 영역은 프로세스 사이에 공유될 수 있으므로 , 커널은 그 영역을 메모리 내의 새로운 위치에 복사하는 대신 영역 참조 계수 (region reference count) 를 증가시킬 수도 있다 . 4. 프로세스와 관련된 파일에 대해 파일 테이블과 inode 테이블 카운터 (counter) 를 증가시킨다 . 5. 부모 프로세스에게는 자식의 ID 번호를 복귀시키고 , 자식 프로세스에게는 0을 복귀시킨다 .
프로세스의 생성 (3)프로세스의 생성 (3)
Linux System Programming 34
프로세스의 생성 (4)프로세스의 생성 (4)
Linux System Programming 35
예제 6-6: fork() 시스템 호출 전에 부모 프로세스의 ID 를 출력하고 for
k() 시스템 호출 후에 부모 및 자식 프로세스의 ID 를 출력하여 fork 함수의 기능을 확인할 수 있는 프로그램을 작성하라 .
현재 수행중인 프로세스의 ID 는 getpid() 함수를 사용하고 , 현재 프로세스의 부모 프로세스 ID 는 getppid() 함수를 사용하여 얻는다 .
프로세스의 생성 (5)프로세스의 생성 (5)
Linux System Programming 36
프로세스의 생성 (6)프로세스의 생성 (6)
#include <stdio.h>
main()
{
int getpid(), getppid();
printf("[%d] parent process id: %d\n",getpid(), getppid());
fork();
printf("\n\t[%d] parent process id: %d\n",getpid(), getppid());
printf("THIS IS FORK SYSTEM CALL TEST.\n");
}
Linux System Programming 37
예제 6-7: 부모 프로세스는 대문자로 A 에서 Z 까지 출력하고 동시에 자식
프로세스는 소문자로 a 에서 z까지 출력하는 프로그램을 작성하여 두 개의 프로세스가 동시에 수행되고 있음을 확인하라 .
프로세스의 생성 (7)프로세스의 생성 (7)
Linux System Programming 38
프로세스의 생성 (8)프로세스의 생성 (8)
main(int argc, char *argv[]){
char ch, first, last;int pid;long i;
if((pid = fork())>0) { /* parent */first = 'A';last = 'Z';
}else if(pid == 0) { /* child */
first = 'a';last = 'z';
}else { /* not fork(2) */
perror(argv[0]);exit(1);
}printf("\n");for(ch = first; ch <= last; ch++) {
/* delay loop */for(i=0; i<= 100000; i++);write(1, &ch, 1);
}}
Linux System Programming 39
다른 프로그램의 호출 :exec
다른 프로그램의 호출 (1)다른 프로그램의 호출 (1)
Linux System Programming 40
다른 프로그램의 호출 (2)다른 프로그램의 호출 (2)
다른 프로그램의 호출 :exec
Linux System Programming 41
다른 프로그램의 호출 (3)다른 프로그램의 호출 (3)
다른 프로그램의 호출 :exec
Linux System Programming 42
다른 프로그램의 호출 (4)다른 프로그램의 호출 (4)
다른 프로그램의 호출 :exec
Linux System Programming 43
다른 프로그램의 호출 (5)다른 프로그램의 호출 (5)
예제 6-8: 다음 프로그램은 exec 시스템 호출에서 사용될 예제로써 명령어 라인에서 준 인수들과 셸 (shell) 환경 변수들을 출력해 준다 .
argv[] 값과 environ 은 exec 시스템 호출시 매개 변수로서 사용될 것이다 .
프로그램을 수행시켜 결과를 분석하라 .
Linux System Programming 44
다른 프로그램의 호출 (6)다른 프로그램의 호출 (6)
extern char **environ;
main(argc, argv) /* program to be exec(2)'ed */int argc;char *argv[];{
char **p;int n;
printf("My input parameters(argv) are: \n");for(n=0; n < argc; n++)
printf(" %2d: '%s'\n", n, argv[n]);
printf("\nMy environment variables are:\n");for(p= environ; *p !=(char *) 0; p++)
printf(" %s\n", *p);
}
Linux System Programming 45
다른 프로그램의 호출 (7)다른 프로그램의 호출 (7)
예제 6-9: execl 시스템 호출 함수를 사용하여 예제 프로그램 ex6-8을
실행시키는 프로그램을 작성하라 . execl 은 argv 인수 리스트를 사용함을 참고하라 .
#include <stdio.h>
main()
{
printf("this is the original program\n");
execl("./ex6-8","ex6-8","parm1","parm2","parm3",(char *) 0);
perror("This line should never get printed\n");
}
Linux System Programming 46
다른 프로그램의 호출 (8)다른 프로그램의 호출 (8)
예제 6-10: execv 시스템 호출 함수를 이용하여 예제 프로그램 ex6-8을
실행시키는 프로그램을 작성하라 .
#include <stdio.h>
main()
{
static char *nargv[] = {
"ex6-8", "parm1", "parm2", "parm3", (char *) 0};
printf("this is the original porgram\n");
execv("./ex6-8",nargv);
perror("This line should never get printed\n");
}
Linux System Programming 47
다른 프로그램의 호출 (9)다른 프로그램의 호출 (9)
예제 6-11: execve 시스템 호출 함수를 이용하여 예제 프로그램 ex6-8을
실행시키는 프로그램을 작성하라 .
#include <stdio.h>
main(){
static char *nargv[] = {"ex6-8", "parm1", "parm2", "parm3", (char *) 0};
static char *nenv[] = {"NAME=value", "nextname=nextvalue", "HOME=/xyz", (char *) 0};
printf("this is the original porgram\n");
execve("./ex6-8",nargv,nenv);perror("This line should never get printed\n");
}
Linux System Programming 48
다른 프로그램의 호출 (10)다른 프로그램의 호출 (10)
예제 6-12: execvp 시스템 호출 함수를 이용하여 예제 프로그램 ex6-8을
실행시키는 프로그램을 작성하라 .
#include <stdio.h>
main()
{
static char *nargv[] = {
"ex6-8", "parm1", "parm2", "parm3", (char *) 0};
printf("this is the original porgram\n");
execvp("ex6-8",nargv);
perror("This line should never get printed\n");
}
Linux System Programming 49
다른 프로그램의 호출 (11)다른 프로그램의 호출 (11)
예제 6-13: exec 시스템 호출 함수를 이용하여 다른 프로그램을
실행시키면 본래의 프로그램은 실행이 중단되는 결과를 가져온다 . 그러므로 프로그램에서 exec 함수를 이용하여 다른 프로그램을 수행시킨 후 중단없이 작업을 계속하려면 fork 를 이용하여 자식 프로세스가 exec 함수를 호출하게 만들면 부모 프로세스의 중단없이 작업을 계속 수행할 수 있다 .
fork 와 exec 함수를 이용하여 부모 프로세스가 중단되지 않도록 exec 함수를 사용하여 LINUX 의 echo 명령어를 실행시키는 프로그램을 작성하라 .
Linux System Programming 50
다른 프로그램의 호출 (12)다른 프로그램의 호출 (12)
main(){
int fork();
if(fork() == 0) {execl("/bin/echo", "echo","this is","message one",(char *) 0);perror("exec one failed");exit(1);
}if(fork() == 0) {
execl("/bin/echo","echo","this is","message two",(char *) 0);perror("exec two failed");exit(2);
}if(fork() == 0) {
execl("/bin/echo","echo","this is","message three",(char *) 0);perror("exec three failed");exit(3);
}printf("Parent program ending\n");
}
Linux System Programming 51
프로세스 종료프로세스 종료프로세스이 종료 :exit
Linux System Programming 52
프로세스의 종료를 기다림 (1)프로세스의 종료를 기다림 (1)
프로세스이 종료를 기다림 : wait wait 는 자식 프로세스가 수행되고 있는 동안 부모 프로세스의
수행을 일시적으로 중단시킨다 . 자식 프로세스가 수행을 마치면 , 기다리던 부모 프로세스는
수행을 재개한다 . 하나 이상의 자식 프로세스가 수행되고 있으면 , wait 는
자식프로세스들 중 하나가 최초로 종료되는 시간에 복귀된다 .
Linux System Programming 53
프로세스이 종료를 기다림 : wait
프로세스의 종료를 기다림 (2)프로세스의 종료를 기다림 (2)
Linux System Programming 54
예제 6-14: fork 시스템 호출 함수를 이용하여 자식 (child) 프로세스를
생성하여 자식 프로세스 및 부모 프로세스의 ID 를 출력하고 부모 프로세스에서는 wait 함수를 이용하여 자식 프로세스의 종료를 기다리는 프로그램을 작성하라 .
또한 wait 함수의 반환값 (return value) 과 자식 프로세스로부터 받을 상태값 (status value) 을 출력시켜라 .
프로세스의 종료를 기다림 (3)프로세스의 종료를 기다림 (3)
Linux System Programming 55
프로세스의 종료를 기다림 (4)프로세스의 종료를 기다림 (4)
#define EXIT_CODE 1
main(int argc, char *argv[]){
int pid, ret, status, fork(), wait();void exit();
if((pid = fork()) ==0) { /* child */printf("child: pid=%d ppid=%d exit_code=%d\n",
getpid(), getppid(), EXIT_CODE);exit(EXIT_CODE);
}
printf("parent: wating for child=%d\n", pid);ret = wait(&status);
printf("parent: return value=%d, ",ret);printf(" child's status=%x", status);printf(" and shifted=%x\n", (status >> 8));
exit(0);}
Linux System Programming 56
예제 6-15: 부모 프로세스에서 두 개의 자식 프로세스를 생성하여 각각 ex
ecl 함수를 이용해서 echo 명령어를 수행시켜 메시지를 출력하고 , 부모 프로세스는 이들 자식 프로세스들이 종료하기를 기다리는 프로그램을 작성하라 .
프로세스의 종료를 기다림 (5)프로세스의 종료를 기다림 (5)
Linux System Programming 57
프로세스의 종료를 기다림 (6)프로세스의 종료를 기다림 (6)
main(int argc, char*argv[])
{
int fork(), wait();
if(fork() == 0) /* child */
execl("/bin/echo","echo","this is","message one",(char *) 0);
if(fork() == 0) /* child */
execl("/bin/echo","echo","this is","message Two",(char *) 0);
printf("parent: wating for children\n");
while(wait((int *) 0) != -1) ; /* null */
printf("parent: all children terminated\n");
exit(0);
}
Linux System Programming 58
예제 6-16: [예제 6-15]를 개선하여 부모 프로세스는 자식 프로세스의
종료를 기다리면서 종료하는 각 프로세스를 식별하여 메시지와 함께 종료 상태 (status)를 출력하는 프로그램을 작성하라 .
프로세스의 종료를 기다림 (7)프로세스의 종료를 기다림 (7)
Linux System Programming 59
main(int argc,char *argv[]){
int child1, child2, fork();int pid, status, wait();
if((child1 = fork()) ==0)execl("/bin/date","date",(char *) 0);
if((child2 = fork()) ==0)execl("/bin/who","who",(char *) 0);
printf("parent: wating for children\n");while((pid = wait(&status)) != -1) {
if(child1 == pid) printf("parent: first child: %d\n",(status>>8));
else if(child2 == pid) printf("parent: second child: %d\n",(status>>8));
}printf("parent: all children terminated\n");exit(0);
}
프로세스의 종료를 기다림 (8)프로세스의 종료를 기다림 (8)
Linux System Programming 60
예제 6-17: C 라이브러리 system() 함수처럼 LINUX 명령어를 매개
변수로 받아 수행시켜 주는 모듈을 fork 와 execlp, 그리고 wait 함수를 이용하여 작성하라 .
모듈 이름을 command() 라 하고 main 에서 LINUX 명령어를 매개 변수로 전달하여 실행시킨다 .
프로세스의 종료를 기다림 (9)프로세스의 종료를 기다림 (9)
Linux System Programming 61
프로세스의 종료를 기다림 (10)프로세스의 종료를 기다림 (10)
command(char *cmd) /* run a shell command from C program */{
int chpid, fork();int w, status, wait();
if((chpid = fork()) == 0) {execlp("sh","sh","-c",cmd,(char *) 0);exit(127);
}
while((w = wait(&status)) != chpid && w != -1) ;if(w == -1) status = -1;return(status >> 8);
}
main(){
printf("%d\n", command("date > Date; cat Date"));printf("%d\n", command("who am i"));
}
Linux System Programming 62
예제 6-18: fork 함수를 이용하여 자식 프로세스를 생성하고 자식
프로세스에서 execl 함수로 LINUX 명령어를 실행시켜 긴 화일을 출력 (cat 명령어 이용 )하는 동안 부모 프로세스가 기다리는 프로그램을 작성하라 .
프로세스의 종료를 기다림 (11)프로세스의 종료를 기다림 (11)
Linux System Programming 63
프로세스의 종료를 기다림 (12)프로세스의 종료를 기다림 (12)
main(int argc, char *argv[]){ int pid; int ret, status;
if((pid = fork()) == 0) /* child */ execl("/bin/cat","cat","/etc/group", (char *) 0); printf("parent: wating for child: %d\n",pid);
ret = wait(&status);
printf("parent: wait's return value: %d,",ret); printf("child's status: %d\n", (status >> 8));
exit(0);}
Linux System Programming 64
예제 6-19: 인수 (argument) 로 받은 명령어를 자식 프로세스를 생성하여
수행시키고 (execvp 함수 이용 ), 명령어의 종료 상태 (exit status) 를 출력하는 프로그램을 작성하라 .
프로세스의 종료를 기다림 (13)프로세스의 종료를 기다림 (13)
Linux System Programming 65
프로세스의 종료를 기다림 (14)프로세스의 종료를 기다림 (14)
main(int argc, char *argv[]){ int fork(); int status, wait();
if(fork() == 0) { execvp(argv[1], &argv[1]); perror(argv[1]); exit(127); } wait(&status); printf("exit status: %d\n", (status >> 8)); exit(0);}
Linux System Programming 66
예제 6-20: Linux 시스템의 셀 인터프리터를 간단하게 구현한 프로그램을
작성하여라 . 프로그램 모듈 :
Ex6-20.h : 최대 인수 수 (MAXARG), 최대 명령어 수 (MAXCMD) 및 명령어의 구조체를 선언한다
Ex6-20a.c : 키보드로 입력된 명령어들의 문법을 검사하고 인수를 분리하여 저장한다
Ex6-20b.c : 프롬프트를 표시하고 명령어를 입력 받는다 Ex6-20.c : 주프로그램으로서 ex6-20b 와 ex6-20a 함수를 호출하고 자식 프로세스를 생성하여 명령어를 실행시킨다
예제 프로그램 : mini-shell예제 프로그램 : mini-shell