linux system programming

66
Linux System Linux System Programming Programming Lecture #6 – 프프프프 프프프 프프

Upload: amaya-contreras

Post on 31-Dec-2015

131 views

Category:

Documents


0 download

DESCRIPTION

Linux System Programming. Lecture #6 – 프로세스 생성과 수행. 프로세스의 소개 (1). 프로세스의 정의 : 프로세스 (Process) 란 실행중인 프로그램을 의미 예 : 파워포인터 프로그램을 실행하였을 경우 - (1) 하드디스크에 설치되어 있는 프로그램 - 저장된 프로그램 (2) 실행하기 위해 메모리에 로딩된 프로그램 - 프로세스 프로세스는 운영체제가 서비스를 제공하는 대상 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Linux System Programming

Linux System Linux System ProgrammingProgramming

Lecture #6 – 프로세스 생성과 수행

Page 2: Linux System Programming

Linux System Programming 2

프로세스의 소개 (1)프로세스의 소개 (1)

프로세스의 정의 : 프로세스 (Process)란 실행중인 프로그램을 의미

예 : 파워포인터 프로그램을 실행하였을 경우 -(1) 하드디스크에 설치되어 있는 프로그램 - 저장된 프로그램(2) 실행하기 위해 메모리에 로딩된 프로그램 - 프로세스

프로세스는 운영체제가 서비스를 제공하는 대상 사용자가 하나의 프로그램을 실행하면 운영체제는 그 프로그램을 실행하는 하나의 프로세스를 생성하고 , 프로세스가 프로그램을 실행하기 위해 요구하는 서비스를 제공한다

Multitasking을 지원하는 운영체제는 동시에 한 개 이상의 프로세스를 생성할 수 있으며 , 이들 프로세스가 동시에 동작하도록 서비스를 제공한다

동일한 프로그램에 대해 여러 개의 프로세스가 생성될 수 있다 예 : 동시에 파워포인터 프로그램을 2개 이상 실행한 경우

프로세스는 상호 독립적으로 동작한다

Page 3: Linux System Programming

Linux System Programming 3

프로세스의 소개 (2)프로세스의 소개 (2)

프로세스의 정의 : Linux 운영체제에서 프로세스간에 계층 구조를 갖는다

Linux 운영체제에서는 fork 시스템 호출에 의하여 프로세스를 생성 프로세스 0을 제외한 모든 프로세스는 다른 프로세스가 fork 시스템 호출을 수행하여 만들어진다 .

fork를 호출한 프로세스를 부모 프로세스라 하고 , 새로 만들어진 프로세스를 자식 프로세스라 한다 .

모든 프로세스는 오직 하나의 부모 프로세스를 가질 수 있지만 , 자식 프로세스는 여러 개를 가질 수 있다 .

Page 4: Linux System Programming

Linux System Programming 4

프로세스의 소개 (3)프로세스의 소개 (3)

프로세스의 정의 : Linux 커널은 각 프로세스들을 프로세스 ID( 정수값 )로

구분한다 프로세스 0은 시스템이 부트될 때 만들어지며 , 프로세스 1 을

fork 한 후에는 스와퍼 (swapper) 가 된다 프로세스 1은 init 프로세스라고 알려져 있는데 , 시스템

내의 다른 모든 프로세스의 조상이 된다

Page 5: Linux System Programming

Linux System Programming 5

프로세스의 소개 (4)프로세스의 소개 (4)

프로세스의 구조 : 실행 가능 파일 (Executable File)

원시 코드 파일을 컴파일하여 생성되는 파일 구조 :

프로그램 텍스트 – 원시 코드를 컴파일하여 생성된 기계어 코드 데이터 영역 – 원시 프로그램에서 정의된 전역 변수 및 상수에 대한 정보를 저장

Page 6: Linux System Programming

Linux System Programming 6

프로세스의 소개 (5)프로세스의 소개 (5)

프로세스의 구조 : 실행 가능 프로그램이 주기억 장치로 적재 (load) 되어

프로세스가 생성되면 텍스트 영역과 액티베이션 (activation) 레코드로 구분되어 존재

액티베이션 레코드는 전역 (global) 데이터 영역과 스택 영역으로 이루어져 있으며 , 전역 데이터 영역은 초기화 데이터와 비초기화 데이터 영역으로 구성

초기화 데이터 영역은 프로그램에서 초기화가 배정된 변수 , 배열이나 구조체 (structure) 등이 저장되며 , 비초기화 데이터 영역에는 초기값을 배정하지 않은 변수 , 배열 , 구조체 등의 기억 장소이다 .

Page 7: Linux System Programming

Linux System Programming 7

프로세스의 소개 (6)프로세스의 소개 (6)

프로세스의 구조 : 운영 체제의 가상 공간에는 커널 프로그램이 저장된 텍스트 (te

xt) 영역과 시스템에서 수행중인 프로세스들을 관리하기 위한 프로세스 테이블들이 저장된 데이터 영역으로 구분

커널 공간에 프로세스 생성과 관련된 데이터 구조 :(1) 프로세스 테이블(2) PCB( 프로세스 제어 블록 )(3) 사용자 영역 (u-area) – 파일 디스크립터 테이블 , OS 스택 등

Page 8: Linux System Programming

Linux System Programming 8

프로세스의 소개 (7)프로세스의 소개 (7)

프로세스의 구조 :

Page 9: Linux System Programming

Linux System Programming 9

프로세스의 소개 (8)프로세스의 소개 (8)

프로세스의 상태 : 프로세스 문맥 (Process Context) 은 프로세스의 현재 상태를

의미 프로세스 문맥은 프로세스의 텍스트 , 전역 사용자 변수들과

데이터 구조들의 값 , 프로세스가 사용하는 기계 레지스터의 값 , 프로세스 테이블 항과 user area 에 저장된 값들 , 사용자 스택과 커널 스택의 내용 등에 의해 정의된다 .

하나의 프로세스가 실행되고 있을 때 , 시스템은 그 프로세스 문맥에서 실행 중이라고 정의

현재 CPU 가 접근하는 메모리 영역을 의미 현재 실행중인 프로세스를 중지하고 새로운 프로세스를 실행하기

위해서는 문맥 교환 (Context Switching) 이 이루어진다 실행 중인 프로세스가 시스템 호출을 요청하면 시스템은 사용자

모드에 커널 모드로 변환하여 실행중인 프로세스 문맥에서 커널 프로그램을 실행한다 (모드 변환 )

Page 10: Linux System Programming

Linux System Programming 10

프로세스의 소개 (9)프로세스의 소개 (9)

프로세스의 상태 :

Page 11: Linux System Programming

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);

Page 12: Linux System Programming

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);}

Page 13: Linux System Programming

Linux System Programming 13

프로세스의 크기 변경 :brk, sbrk

프로세스의 크기 변경 (1)프로세스의 크기 변경 (1)

Page 14: Linux System Programming

Linux System Programming 14

프로세스의 크기 변경 :brk, sbrk

프로세스의 크기 변경 (2)프로세스의 크기 변경 (2)

Page 15: Linux System Programming

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);

Page 16: Linux System Programming

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);

}

Page 17: Linux System Programming

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 로 세트한다

Page 18: Linux System Programming

Linux System Programming 18

프로세스의 사용자 식별 (2)프로세스의 사용자 식별 (2)

프로세스의 사용자 식별 (ID):setuid, setgid

Page 19: Linux System Programming

Linux System Programming 19

예제 6-2: 아래의 조건에 따라 읽기 전용 파일을 생성하는 프로그램을 작성하고

실사용자와 유효 사용자의 관계를 확인하라 .

1. 실사용자와 유효 사용자의 ID 를 출력한다 .

2. fopen() 함수를 사용하여 파일 접근의 성공과 실패를 검사한다 .

3. setuid 함수를 이용하여 실사용자와 유효 사용자가 동일하게 만든다 .

4. 1-2 를 반복한다 .

실험은 다음 단계로 한다 .

1. 프로그램을 실행하고 출력을 관측한다 .

2. 그룹 멤버가 프로그램을 수행할 수 있도록 접근 허가를 수정하여 그룹

멤버로 하여금 프로그램을 수행시킨다 .

3. set-user-id 비트를 설정하고 그룹 멤버로 하여금 프로그램을 수행시킨다 .

프로세스의 사용자 식별 (3)프로세스의 사용자 식별 (3)

Page 20: Linux System Programming

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); }

Page 21: Linux System Programming

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); }}

Page 22: Linux System Programming

Linux System Programming 22

예제 6-3:

아래 주어진 옵션 (option) 에 따라 프로세스의 정보를 출력하는

프로그램을 작성하라 . 옵션 (option) 의 분해에는 getopt

함수를 사용한다 .

-i : 사용자 (user) 와 그룹 (group) 의 실사용자 및 유효 사용자 ID

를 다음의 함수를 사용하여 출력한다 .

프로세스의 사용자 식별 (6)프로세스의 사용자 식별 (6)

Page 23: Linux System Programming

Linux System Programming 23

예제 6-3: -s : setpgrp() 함수를 이용하여 프로세스를 새로운 그룹에 포함시킨다

-p : 프로세스 , 부모 프로세스 , 그룹 프로세스 ID 를 다음 함수를

이용하여 출력한다 .

-u : ulimit() 함수를 호출하여 프로세스의 크기에 대한 값을

출력한다 .

-Unewlimit: ulimit() 함수를 이용하여 프로세스 크기에 대한 값을

새로 설정한다 .

프로세스의 사용자 식별 (7)프로세스의 사용자 식별 (7)

Page 24: Linux System Programming

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;

Page 25: Linux System Programming

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;

}

}

Page 26: Linux System Programming

Linux System Programming 26

프로세스의 환경 변수 :getenv, putenv LINUX 프로세스의 환경은 셸 (shell) 변수들로써 이루어져 있다 . 셸 (shell) 변수들은 스택 (stack) 에 저장되어 있고 그들을 접근하는

가장 간단한 방법은 명령어 행의 인수 (argument) 들을 접근하는 것처럼 주함수 (main function) 에 파라미터를 하나 더 추가하는 것이다 .

전역 변수 envion 은 환경 변수들이 저장된 테이블의 시작 주소를 가지고 있다 . 그러므로 프로그램에서 다음과 같이 선언하여 환경 변수에 접근할 수 있다 .

프로세스의 환경변수 (1)프로세스의 환경변수 (1)

Page 27: Linux System Programming

Linux System Programming 27

프로세스의 환경 변수 :getenv, putenv

프로세스의 환경변수 (2)프로세스의 환경변수 (2)

Page 28: Linux System Programming

Linux System Programming 28

예제 6-5: 자신의 환경 변수들을 모두 출력하는 프로그램을 작성하라 . 환경 변수 TZ(Time Zone) 을 변경한 후 변경된 내용을 출력하여

확인하라 . 새로운 환경 변수 WARNING에 값을 설정한 후 그 내용을

출력시켜라 .

프로세스의 환경변수 (3)프로세스의 환경변수 (3)

Page 29: Linux System Programming

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"));

}

Page 30: Linux System Programming

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);

}

Page 31: Linux System Programming

Linux System Programming 31

프로세스의 생성 :fork

프로세스의 생성 (1)프로세스의 생성 (1)

Page 32: Linux System Programming

Linux System Programming 32

프로세스의 생성 (2)프로세스의 생성 (2)

Page 33: Linux System Programming

Linux System Programming 33

프로세스의 생성 :fork 커널은 fork 수행시 다음과 같은 순서로 동작한다 .

1. 새로운 프로세스를 위해 프로세스 테이블 항을 할당한다 . 2. 자식 프로세스에게 고유의 ID 번호를 부여한다 . 3. 부모 프로세스의 내용을 논리적으로 복사한다 . 예를 들면 , 텍스트 영역과 같은 프로세스의 일부 영역은 프로세스 사이에 공유될 수 있으므로 , 커널은 그 영역을 메모리 내의 새로운 위치에 복사하는 대신 영역 참조 계수 (region reference count) 를 증가시킬 수도 있다 . 4. 프로세스와 관련된 파일에 대해 파일 테이블과 inode 테이블 카운터 (counter) 를 증가시킨다 . 5. 부모 프로세스에게는 자식의 ID 번호를 복귀시키고 , 자식 프로세스에게는 0을 복귀시킨다 .

프로세스의 생성 (3)프로세스의 생성 (3)

Page 34: Linux System Programming

Linux System Programming 34

프로세스의 생성 (4)프로세스의 생성 (4)

Page 35: Linux System Programming

Linux System Programming 35

예제 6-6: fork() 시스템 호출 전에 부모 프로세스의 ID 를 출력하고 for

k() 시스템 호출 후에 부모 및 자식 프로세스의 ID 를 출력하여 fork 함수의 기능을 확인할 수 있는 프로그램을 작성하라 .

현재 수행중인 프로세스의 ID 는 getpid() 함수를 사용하고 , 현재 프로세스의 부모 프로세스 ID 는 getppid() 함수를 사용하여 얻는다 .

프로세스의 생성 (5)프로세스의 생성 (5)

Page 36: Linux System Programming

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");

}

Page 37: Linux System Programming

Linux System Programming 37

예제 6-7: 부모 프로세스는 대문자로 A 에서 Z 까지 출력하고 동시에 자식

프로세스는 소문자로 a 에서 z까지 출력하는 프로그램을 작성하여 두 개의 프로세스가 동시에 수행되고 있음을 확인하라 .

프로세스의 생성 (7)프로세스의 생성 (7)

Page 38: Linux System Programming

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);

}}

Page 39: Linux System Programming

Linux System Programming 39

다른 프로그램의 호출 :exec

다른 프로그램의 호출 (1)다른 프로그램의 호출 (1)

Page 40: Linux System Programming

Linux System Programming 40

다른 프로그램의 호출 (2)다른 프로그램의 호출 (2)

다른 프로그램의 호출 :exec

Page 41: Linux System Programming

Linux System Programming 41

다른 프로그램의 호출 (3)다른 프로그램의 호출 (3)

다른 프로그램의 호출 :exec

Page 42: Linux System Programming

Linux System Programming 42

다른 프로그램의 호출 (4)다른 프로그램의 호출 (4)

다른 프로그램의 호출 :exec

Page 43: Linux System Programming

Linux System Programming 43

다른 프로그램의 호출 (5)다른 프로그램의 호출 (5)

예제 6-8: 다음 프로그램은 exec 시스템 호출에서 사용될 예제로써 명령어 라인에서 준 인수들과 셸 (shell) 환경 변수들을 출력해 준다 .

argv[] 값과 environ 은 exec 시스템 호출시 매개 변수로서 사용될 것이다 .

프로그램을 수행시켜 결과를 분석하라 .

Page 44: Linux System Programming

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);

}

Page 45: Linux System Programming

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");

}

Page 46: Linux System Programming

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");

}

Page 47: Linux System Programming

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");

}

Page 48: Linux System Programming

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");

}

Page 49: Linux System Programming

Linux System Programming 49

다른 프로그램의 호출 (11)다른 프로그램의 호출 (11)

예제 6-13: exec 시스템 호출 함수를 이용하여 다른 프로그램을

실행시키면 본래의 프로그램은 실행이 중단되는 결과를 가져온다 . 그러므로 프로그램에서 exec 함수를 이용하여 다른 프로그램을 수행시킨 후 중단없이 작업을 계속하려면 fork 를 이용하여 자식 프로세스가 exec 함수를 호출하게 만들면 부모 프로세스의 중단없이 작업을 계속 수행할 수 있다 .

fork 와 exec 함수를 이용하여 부모 프로세스가 중단되지 않도록 exec 함수를 사용하여 LINUX 의 echo 명령어를 실행시키는 프로그램을 작성하라 .

Page 50: Linux System Programming

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");

}

Page 51: Linux System Programming

Linux System Programming 51

프로세스 종료프로세스 종료프로세스이 종료 :exit

Page 52: Linux System Programming

Linux System Programming 52

프로세스의 종료를 기다림 (1)프로세스의 종료를 기다림 (1)

프로세스이 종료를 기다림 : wait wait 는 자식 프로세스가 수행되고 있는 동안 부모 프로세스의

수행을 일시적으로 중단시킨다 . 자식 프로세스가 수행을 마치면 , 기다리던 부모 프로세스는

수행을 재개한다 . 하나 이상의 자식 프로세스가 수행되고 있으면 , wait 는

자식프로세스들 중 하나가 최초로 종료되는 시간에 복귀된다 .

Page 53: Linux System Programming

Linux System Programming 53

프로세스이 종료를 기다림 : wait

프로세스의 종료를 기다림 (2)프로세스의 종료를 기다림 (2)

Page 54: Linux System Programming

Linux System Programming 54

예제 6-14: fork 시스템 호출 함수를 이용하여 자식 (child) 프로세스를

생성하여 자식 프로세스 및 부모 프로세스의 ID 를 출력하고 부모 프로세스에서는 wait 함수를 이용하여 자식 프로세스의 종료를 기다리는 프로그램을 작성하라 .

또한 wait 함수의 반환값 (return value) 과 자식 프로세스로부터 받을 상태값 (status value) 을 출력시켜라 .

프로세스의 종료를 기다림 (3)프로세스의 종료를 기다림 (3)

Page 55: Linux System Programming

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);}

Page 56: Linux System Programming

Linux System Programming 56

예제 6-15: 부모 프로세스에서 두 개의 자식 프로세스를 생성하여 각각 ex

ecl 함수를 이용해서 echo 명령어를 수행시켜 메시지를 출력하고 , 부모 프로세스는 이들 자식 프로세스들이 종료하기를 기다리는 프로그램을 작성하라 .

프로세스의 종료를 기다림 (5)프로세스의 종료를 기다림 (5)

Page 57: Linux System Programming

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);

}

Page 58: Linux System Programming

Linux System Programming 58

예제 6-16: [예제 6-15]를 개선하여 부모 프로세스는 자식 프로세스의

종료를 기다리면서 종료하는 각 프로세스를 식별하여 메시지와 함께 종료 상태 (status)를 출력하는 프로그램을 작성하라 .

프로세스의 종료를 기다림 (7)프로세스의 종료를 기다림 (7)

Page 59: Linux System Programming

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)

Page 60: Linux System Programming

Linux System Programming 60

예제 6-17: C 라이브러리 system() 함수처럼 LINUX 명령어를 매개

변수로 받아 수행시켜 주는 모듈을 fork 와 execlp, 그리고 wait 함수를 이용하여 작성하라 .

모듈 이름을 command() 라 하고 main 에서 LINUX 명령어를 매개 변수로 전달하여 실행시킨다 .

프로세스의 종료를 기다림 (9)프로세스의 종료를 기다림 (9)

Page 61: Linux System Programming

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"));

}

Page 62: Linux System Programming

Linux System Programming 62

예제 6-18: fork 함수를 이용하여 자식 프로세스를 생성하고 자식

프로세스에서 execl 함수로 LINUX 명령어를 실행시켜 긴 화일을 출력 (cat 명령어 이용 )하는 동안 부모 프로세스가 기다리는 프로그램을 작성하라 .

프로세스의 종료를 기다림 (11)프로세스의 종료를 기다림 (11)

Page 63: Linux System Programming

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);}

Page 64: Linux System Programming

Linux System Programming 64

예제 6-19: 인수 (argument) 로 받은 명령어를 자식 프로세스를 생성하여

수행시키고 (execvp 함수 이용 ), 명령어의 종료 상태 (exit status) 를 출력하는 프로그램을 작성하라 .

프로세스의 종료를 기다림 (13)프로세스의 종료를 기다림 (13)

Page 65: Linux System Programming

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);}

Page 66: Linux System Programming

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