1 / 66

Linux System Programming

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

Download Presentation

Linux System Programming

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. Linux System Programming Lecture #6 –프로세스 생성과 수행

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

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

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

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

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

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

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

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

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

  11. 프로세스의 소개 (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) 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. 프로세스의 크기 변경 (1) • 프로세스의 크기 변경:brk, sbrk Linux System Programming

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

  15. 프로세스의 크기 변경 (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); bv = sbrk(0); printf("Current break value is %07o\n\n",bv); Linux System Programming

  16. 프로세스의 크기 변경 (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) • 프로세스의 사용자 식별(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) • 프로세스의 사용자 식별(ID):setuid, setgid Linux System Programming

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

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

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

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

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

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

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

  29. 프로세스의 환경변수 (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) 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. 프로세스의 생성 (1) • 프로세스의 생성:fork Linux System Programming

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

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

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

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

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

  38. 프로세스의 생성 (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. 다른 프로그램의 호출 (1) • 다른 프로그램의 호출:exec Linux System Programming

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

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

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

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

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

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

More Related