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

Linux System Programming
Basic of Buffer Over Flow
Linux/UNIX Programming APUE (The Environment of a UNIX Process)
Activation Records & Recursion
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express.
C 프로그래밍 소개 숙명여대 창병모 2011 가을.
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
제3장 추가 실습 3장 관련 C 언어 프로그래밍 실습.
Department of Computer Engineering
공학기초설계 Youn-Hee Han 강의 소개 & MinGW & gcc 공학기초설계 Youn-Hee Han
1 유닉스 시스템 프로그래밍 개요.
Multi-thread Programming
처음으로 배우는 C 프로그래밍 제2부 기초 제5장 반복문.
쉽게 풀어쓴 C언어 Express 제9장 함수와 변수 C Express.
6 프로세스 생성과 실행.
6 프로세스 생성과 실행.
버퍼 오버플로우에 대한 대책과 발전된 공격 안전한 함수 사용 버퍼 오버플로우에 취약한 함수 사용하지 않기
Linux System Programming
쉽게 풀어쓴 C언어 Express 제16장 파일 입출력 C Express Slide 1 (of 23)
7. while 문의 흐름 제어.
10장 메모리 관리.
Department of Computer Engineering
Department of Computer Engineering
fork로 생성한 자식 프로세스에서 exec 함수군을 호출
멀티쓰레드 기반의 서버구현 School of Electronics and Information.
Computer Architecture
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express.
Term Project Team Member
프로세스 생성[1] 프로그램 실행 : system(3) #include <stdlib.h>
6장 파일 및 레코드 잠금.
C언어 프로그래밍의 이해 Ch14. 파일 입출력.
Department of Computer Engineering
Linux/UNIX Programming APUE (The Environment of a Linux/Unix Process)
10장 C 표준 파일 입출력 子曰 學而時習(실습?)之 不亦悅乎.
5 프로세스 정보.
17강 파일처리함수(1) 강 의 내 용 파일 입출력의 개념 파일포인터를 이용한 입출력 파일 입출력 과정
adopted from KNK C Programming : A Modern Approach
Signal & Inter-Process Communication
제4장 유닉스 쉘 숙명여대 창병모 2011 가을.
C언어 프로그래밍의 이해 Ch13. 선행처리기와 주석문.
CGI (Common Gateway Interface)
제 6장 함수 Hello!! C 언어 강성호 김학배 최우영.
함수와 변수 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원 E304호,
제어문 & 반복문 C스터디 2주차.
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
Stepper Motor 디바이스 드라이버
6장 반복제어문 for 문 while 문 do while 문 기타 제어문.
23. Unix 시스템 커널. 개요 커널의 기본 서비스 커널의 특징 참고서적 프로세스 관리 장치 관리 파일 관리 가상 메모리
Department of Computer Engineering
8. 리눅스의 내부 군자삼락 [君子三樂] 청출어람이청어람 [ 靑出於藍而靑於藍 ] Why Linux ?
쉽게 풀어쓴 C언어 Express 제6장 조건문 C Express Slide 1 (of 28)
Execution with Unnecessary Privileges
쉽게 풀어쓴 C언어 Express 제6장 조건문 C Express.
C언어 프로그래밍의 이해 Ch03. 기본 자료형, 변수와 상수.
반복문의 기능 반복문 반복문 특정 영역을 특정 조건이 만족하는 동안에 반복 실행하기 위한 문장 while문
실습과제 1번 생성된 파일 basic.txt를 프로젝트 폴더에서 메모장으로 열고 내용을 확인
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
argc, argv 의 사용방법 #include <stdio.h>
Signal & Inter-Process Communication
C 13장. 입출력 라이브러리 #include <stdio.h> int main(void) { int num;
C.
배열, 포인터, 함수 Review & 과제 1, 2.
프로그래밍 기법 최적화 프로그래밍.
⊙ 입출력 처리란? data를 입력장치로부터 program 내부로 읽어 들이거나
Presentation transcript:

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

프로세스의 소개 (1) 프로세스의 정의: 프로세스(Process)란 실행중인 프로그램을 의미 예: 파워포인터 프로그램을 실행하였을 경우 - (1) 하드디스크에 설치되어 있는 프로그램 - 저장된 프로그램 (2) 실행하기 위해 메모리에 로딩된 프로그램 - 프로세스 프로세스는 운영체제가 서비스를 제공하는 대상 사용자가 하나의 프로그램을 실행하면 운영체제는 그 프로그램을 실행하는 하나의 프로세스를 생성하고, 프로세스가 프로그램을 실행하기 위해 요구하는 서비스를 제공한다 Multitasking을 지원하는 운영체제는 동시에 한 개 이상의 프로세스를 생성할 수 있으며, 이들 프로세스가 동시에 동작하도록 서비스를 제공한다 동일한 프로그램에 대해 여러 개의 프로세스가 생성될 수 있다 예: 동시에 파워포인터 프로그램을 2개 이상 실행한 경우 프로세스는 상호 독립적으로 동작한다 Linux System Programming

프로세스의 소개 (2) 프로세스의 정의: Linux 운영체제에서 프로세스간에 계층 구조를 갖는다 Linux 운영체제에서는 fork 시스템 호출에 의하여 프로세스를 생성 프로세스 0을 제외한 모든 프로세스는 다른 프로세스가 fork 시스템 호출을 수행하여 만들어진다. fork를 호출한 프로세스를 부모 프로세스라 하고, 새로 만들어진 프로세스를 자식 프로세스라 한다. 모든 프로세스는 오직 하나의 부모 프로세스를 가질 수 있지만, 자식 프로세스는 여러 개를 가질 수 있다. Linux System Programming

프로세스의 소개 (3) 프로세스의 정의: Linux 커널은 각 프로세스들을 프로세스 ID(정수값)로 구분한다 프로세스 0은 시스템이 부트될 때 만들어지며, 프로세스 1을 fork한 후에는 스와퍼(swapper)가 된다 프로세스 1은 init 프로세스라고 알려져 있는데, 시스템 내의 다른 모든 프로세스의 조상이 된다 Linux System Programming

프로세스의 소개 (4) 프로세스의 구조: 실행 가능 파일(Executable File) 원시 코드 파일을 컴파일하여 생성되는 파일 구조: 프로그램 텍스트 – 원시 코드를 컴파일하여 생성된 기계어 코드 데이터 영역 – 원시 프로그램에서 정의된 전역 변수 및 상수에 대한 정보를 저장 Linux System Programming

프로세스의 소개 (5) 프로세스의 구조: 실행 가능 프로그램이 주기억 장치로 적재(load)되어 프로세스가 생성되면 텍스트 영역과 액티베이션(activation) 레코드로 구분되어 존재 액티베이션 레코드는 전역(global) 데이터 영역과 스택 영역으로 이루어져 있으며, 전역 데이터 영역은 초기화 데이터와 비초기화 데이터 영역으로 구성 초기화 데이터 영역은 프로그램에서 초기화가 배정된 변수, 배열이나 구조체(structure) 등이 저장되며, 비초기화 데이터 영역에는 초기값을 배정하지 않은 변수, 배열, 구조체 등의 기억 장소이다. Linux System Programming

프로세스의 소개 (6) 프로세스의 구조: 운영 체제의 가상 공간에는 커널 프로그램이 저장된 텍스트(text) 영역과 시스템에서 수행중인 프로세스들을 관리하기 위한 프로세스 테이블들이 저장된 데이터 영역으로 구분 커널 공간에 프로세스 생성과 관련된 데이터 구조: (1) 프로세스 테이블 (2) PCB(프로세스 제어 블록) (3) 사용자 영역(u-area) – 파일 디스크립터 테이블, OS 스택 등 Linux System Programming

프로세스의 소개 (7) 프로세스의 구조: Linux System Programming

프로세스의 소개 (8) 프로세스의 상태: 프로세스 문맥(Process Context)은 프로세스의 현재 상태를 의미 프로세스 문맥은 프로세스의 텍스트, 전역 사용자 변수들과 데이터 구조들의 값, 프로세스가 사용하는 기계 레지스터의 값, 프로세스 테이블 항과 user area에 저장된 값들, 사용자 스택과 커널 스택의 내용 등에 의해 정의된다. 하나의 프로세스가 실행되고 있을 때, 시스템은 그 프로세스 문맥에서 실행 중이라고 정의 현재 CPU가 접근하는 메모리 영역을 의미 현재 실행중인 프로세스를 중지하고 새로운 프로세스를 실행하기 위해서는 문맥 교환(Context Switching)이 이루어진다 실행 중인 프로세스가 시스템 호출을 요청하면 시스템은 사용자 모드에 커널 모드로 변환하여 실행중인 프로세스 문맥에서 커널 프로그램을 실행한다(모드 변환) Linux System Programming

프로세스의 소개 (9) 프로세스의 상태: Linux System Programming

프로세스의 소개 (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

프로세스의 소개 (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

프로세스의 크기 변경 (1) 프로세스의 크기 변경:brk, sbrk Linux System Programming

프로세스의 크기 변경 (2) 프로세스의 크기 변경:brk, sbrk Linux System Programming

프로세스의 크기 변경 (3) 예제 6-4: brk와 sbrk 시스템 호출을 이용하여 수행중인 프로세스의 크기를 설정하고 출력하는 프로그램을 작성하라. 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); Linux System Programming

프로세스의 크기 변경 (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(-1024); /* memory deallocation: -02000 */ } Linux System Programming

프로세스의 사용자 식별 (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

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

프로세스의 사용자 식별 (3) 예제 6-2: 아래의 조건에 따라 읽기 전용 파일을 생성하는 프로그램을 작성하고 실사용자와 유효 사용자의 관계를 확인하라. 1. 실사용자와 유효 사용자의 ID를 출력한다. 2. fopen() 함수를 사용하여 파일 접근의 성공과 실패를 검사한다. 3. setuid 함수를 이용하여 실사용자와 유효 사용자가 동일하게 만든다. 4. 1-2를 반복한다. 실험은 다음 단계로 한다. 1. 프로그램을 실행하고 출력을 관측한다. 2. 그룹 멤버가 프로그램을 수행할 수 있도록 접근 허가를 수정하여 그룹 멤버로 하여금 프로그램을 수행시킨다. 3. set-user-id 비트를 설정하고 그룹 멤버로 하여금 프로그램을 수행시킨다. Linux System Programming

프로세스의 사용자 식별 (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

프로세스의 사용자 식별 (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

프로세스의 사용자 식별 (6) 예제 6-3: 아래 주어진 옵션(option)에 따라 프로세스의 정보를 출력하는 프로그램을 작성하라. 옵션(option)의 분해에는 getopt함수를 사용한다.  -i : 사용자(user)와 그룹(group)의 실사용자 및 유효 사용자 ID를 다음의 함수를 사용하여 출력한다. Linux System Programming

프로세스의 사용자 식별 (7) 예제 6-3: -s : setpgrp() 함수를 이용하여 프로세스를 새로운 그룹에 포함시킨다 -p : 프로세스, 부모 프로세스, 그룹 프로세스 ID를 다음 함수를 이용하여 출력한다.   -u :  ulimit() 함수를 호출하여 프로세스의 크기에 대한 값을 출력한다. -Unewlimit:  ulimit() 함수를 이용하여 프로세스 크기에 대한 값을 새로 설정한다. Linux System Programming

프로세스의 사용자 식별 (8) #include <stdio.h> #define GET_FSLIM 1 #define SET_FSLIM 2 extern 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

프로세스의 사용자 식별 (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"); case 'u': printf("ulimit = %ld\n",ulimit(GET_FSLIM,0L)); } Linux System Programming

프로세스의 환경변수 (1) 프로세스의 환경 변수:getenv, putenv LINUX 프로세스의 환경은 셸(shell) 변수들로써 이루어져 있다. 셸(shell) 변수들은 스택(stack)에 저장되어 있고 그들을 접근하는 가장 간단한 방법은 명령어 행의 인수(argument)들을 접근하는 것처럼 주함수(main function)에 파라미터를 하나 더 추가하는 것이다. 전역 변수 envion은 환경 변수들이 저장된 테이블의 시작 주소를 가지고 있다. 그러므로 프로그램에서 다음과 같이 선언하여 환경 변수에 접근할 수 있다. Linux System Programming

프로세스의 환경변수 (2) 프로세스의 환경 변수:getenv, putenv Linux System Programming

프로세스의 환경변수 (3) 예제 6-5: 자신의 환경 변수들을 모두 출력하는 프로그램을 작성하라. 환경 변수 TZ(Time Zone)을 변경한 후 변경된 내용을 출력하여 확인하라. 새로운 환경 변수 WARNING에 값을 설정한 후 그 내용을 출력시켜라. Linux System Programming

프로세스의 환경변수 (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

프로세스의 환경변수 (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

프로세스의 생성 (1) 프로세스의 생성:fork Linux System Programming

프로세스의 생성 (2) Linux System Programming

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

프로세스의 생성 (4) Linux System Programming

프로세스의 생성 (5) 예제 6-6: fork() 시스템 호출 전에 부모 프로세스의 ID를 출력하고 fork() 시스템 호출 후에 부모 및 자식 프로세스의 ID를 출력하여 fork 함수의 기능을 확인할 수 있는 프로그램을 작성하라. 현재 수행중인 프로세스의 ID는 getpid() 함수를 사용하고, 현재 프로세스의 부모 프로세스 ID는 getppid() 함수를 사용하여 얻는다. Linux System Programming

프로세스의 생성 (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

프로세스의 생성 (7) 예제 6-7: 부모 프로세스는 대문자로 A에서 Z까지 출력하고 동시에 자식 프로세스는 소문자로 a에서 z까지 출력하는 프로그램을 작성하여 두 개의 프로세스가 동시에 수행되고 있음을 확인하라. Linux System Programming

프로세스의 생성 (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

다른 프로그램의 호출 (1) 다른 프로그램의 호출:exec Linux System Programming

다른 프로그램의 호출 (2) 다른 프로그램의 호출:exec Linux System Programming

다른 프로그램의 호출 (3) 다른 프로그램의 호출:exec Linux System Programming

다른 프로그램의 호출 (4) 다른 프로그램의 호출:exec Linux System Programming

다른 프로그램의 호출 (5) 예제 6-8: 다음 프로그램은 exec 시스템 호출에서 사용될 예제로써 명령어 라인에서 준 인수들과 셸(shell) 환경 변수들을 출력해 준다. argv[] 값과 environ은 exec 시스템 호출시 매개 변수로서 사용될 것이다. 프로그램을 수행시켜 결과를 분석하라. Linux System Programming

다른 프로그램의 호출 (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

다른 프로그램의 호출 (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

다른 프로그램의 호출 (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

다른 프로그램의 호출 (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

다른 프로그램의 호출 (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

다른 프로그램의 호출 (11) 예제 6-13: exec 시스템 호출 함수를 이용하여 다른 프로그램을 실행시키면 본래의 프로그램은 실행이 중단되는 결과를 가져온다. 그러므로 프로그램에서 exec 함수를 이용하여 다른 프로그램을 수행시킨 후 중단없이 작업을 계속하려면 fork를 이용하여 자식 프로세스가 exec 함수를 호출하게 만들면 부모 프로세스의 중단없이 작업을 계속 수행할 수 있다. fork와 exec 함수를 이용하여 부모 프로세스가 중단되지 않도록 exec 함수를 사용하여 LINUX의 echo 명령어를 실행시키는 프로그램을 작성하라. Linux System Programming

다른 프로그램의 호출 (12) main() { int fork(); if(fork() == 0) { execl("/bin/echo", "echo","this is","message one",(char *) 0); perror("exec one failed"); exit(1); } execl("/bin/echo","echo","this is","message two",(char *) 0); perror("exec two failed"); exit(2); execl("/bin/echo","echo","this is","message three",(char *) 0); perror("exec three failed"); exit(3); printf("Parent program ending\n"); Linux System Programming

프로세스 종료 프로세스이 종료:exit Linux System Programming

프로세스의 종료를 기다림 (1) 프로세스이 종료를 기다림: wait 자식 프로세스가 수행을 마치면, 기다리던 부모 프로세스는 수행을 재개한다. 하나 이상의 자식 프로세스가 수행되고 있으면, wait는 자식프로세스들 중 하나가 최초로 종료되는 시간에 복귀된다. Linux System Programming

프로세스의 종료를 기다림 (2) 프로세스이 종료를 기다림: wait Linux System Programming

프로세스의 종료를 기다림 (3) 예제 6-14: fork 시스템 호출 함수를 이용하여 자식(child) 프로세스를 생성하여 자식 프로세스 및 부모 프로세스의 ID를 출력하고 부모 프로세스에서는 wait 함수를 이용하여 자식 프로세스의 종료를 기다리는 프로그램을 작성하라. 또한 wait 함수의 반환값(return value)과 자식 프로세스로부터 받을 상태값(status value)을 출력시켜라. Linux System Programming

프로세스의 종료를 기다림 (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

프로세스의 종료를 기다림 (5) 예제 6-15: 부모 프로세스에서 두 개의 자식 프로세스를 생성하여 각각 execl 함수를 이용해서 echo 명령어를 수행시켜 메시지를 출력하고, 부모 프로세스는 이들 자식 프로세스들이 종료하기를 기다리는 프로그램을 작성하라. Linux System Programming

프로세스의 종료를 기다림 (6) main(int argc, char*argv[]) { int fork(), wait(); if(fork() == 0) /* child */ execl("/bin/echo","echo","this is","message one",(char *) 0); 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

프로세스의 종료를 기다림 (7) 예제 6-16: [예제 6-15]를 개선하여 부모 프로세스는 자식 프로세스의 종료를 기다리면서 종료하는 각 프로세스를 식별하여 메시지와 함께 종료 상태(status)를 출력하는 프로그램을 작성하라. Linux System Programming

프로세스의 종료를 기다림 (8) 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); Linux System Programming

프로세스의 종료를 기다림 (9) 예제 6-17: C 라이브러리 system() 함수처럼 LINUX 명령어를 매개 변수로 받아 수행시켜 주는 모듈을 fork와 execlp, 그리고 wait 함수를 이용하여 작성하라. 모듈 이름을 command()라 하고 main에서 LINUX 명령어를 매개 변수로 전달하여 실행시킨다. Linux System Programming

프로세스의 종료를 기다림 (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

프로세스의 종료를 기다림 (11) 예제 6-18: fork 함수를 이용하여 자식 프로세스를 생성하고 자식 프로세스에서 execl 함수로 LINUX 명령어를 실행시켜 긴 화일을 출력(cat 명령어 이용)하는 동안 부모 프로세스가 기다리는 프로그램을 작성하라. Linux System Programming

프로세스의 종료를 기다림 (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

프로세스의 종료를 기다림 (13) 예제 6-19: 인수(argument)로 받은 명령어를 자식 프로세스를 생성하여 수행시키고(execvp 함수 이용), 명령어의 종료 상태(exit status)를 출력하는 프로그램을 작성하라. Linux System Programming

프로세스의 종료를 기다림 (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

예제 프로그램: mini-shell 예제 6-20: Linux 시스템의 셀 인터프리터를 간단하게 구현한 프로그램을 작성하여라. 프로그램 모듈: Ex6-20.h : 최대 인수 수(MAXARG), 최대 명령어 수(MAXCMD) 및 명령어의 구조체를 선언한다 Ex6-20a.c : 키보드로 입력된 명령어들의 문법을 검사하고 인수를 분리하여 저장한다 Ex6-20b.c : 프롬프트를 표시하고 명령어를 입력 받는다 Ex6-20.c : 주프로그램으로서 ex6-20b와 ex6-20a 함수를 호출하고 자식 프로세스를 생성하여 명령어를 실행시킨다 Linux System Programming