280 likes | 304 Views
Environment of UNIX Processes. [Slides from Prof. Yangsae Moon]. Process 실행. exec system call. Kernel. user process. C start-up routine. return. call. int main(int argc, char * argv[]);. main() function. int main(int argc, char *argv[]); argc : the number of command-line arguments
E N D
Environment of UNIX Processes [Slides from Prof. Yangsae Moon]
Process 실행 exec system call Kernel user process C start-up routine return call int main(int argc, char * argv[]);
main() function • int main(int argc, char *argv[]); • argc : the number of command-line arguments • argv[]: an array of pointers to the arguments • C Start-Up Routine • Started by the kernel (by the exec system call) • Take the command-line arguments and the environment from the kernel
Process Termination • Normal Termination • Return from main() • Calling exit() // with cleanup process • Calling _exit() // without cleanup process • Abnormal Termination • Calling abort() • Terminated by a signal
exit() #include <stdlib.h> void exit(int status); • 프로세스를 정상적으로 종료한다. • Cleanup Processing 을 수행한다. • 모든 열려진 스트림(파일 등)을 닫고, • 출력 버퍼의 내용을 디스크에 쓴다. • status • the exit status of a process (프로세스의 리턴 값으로 이해할 수 있음) • 이 값은 UNIX shell 에 의해서 사용됨 (Shell Programming에서 이용할 수 있음)
_exit() #include <unistd.h> void _exit(int status); • 프로세스를 정상적으로 종료한다. • Kernel로 즉시 리턴한다.(Cleanup Processing을 수행하지 않는다.)
atexit() #include <stdlib.h> void atexit(void (*func)(void)); returns: 0 if OK, nonzero on error • exit handler 를 등록한다. • 프로그램이 종료할 때(exit()이 호출되었을 때) 수행하는 함수들을 등록 • 프로세스당 32개까지 등록 가능함 • func • An exit handler • A function pointer • exit()은 exit handler들을 등록된 역순으로 호출한다.
C Program Start and Termination _exit user function exit handler call return …… exit (does not return) return call call return _exit exit function exit (does not return) main function user process exit handler return call call return exit (does not return) standard I/O cleanup C start-up routine _exit exec kernel
예제: exit handlers (1/2) /* doatexit.c */ static void my_exit1(void), my_exit2(void); int main(void) { if (atexit(my_exit2) != 0) perror("can't register my_exit2"); if (atexit(my_exit1) != 0) perror("can't register my_exit1"); if (atexit(my_exit1) != 0) perror("can't register my_exit1"); printf("main is done\n"); return 0; } static void my_exit1(void) { printf("first exit handler\n"); } static void my_exit2(void) { printf("second exit handler\n"); }
예제: exit handlers (2/2) • 실행 결과
Command-Line Arguments • exec() can pass command-line arguments to a new program. • argc에 Argument 개수를, • argv에 Argument를 각각 전달한다. • Part of normal operation of Unix Shells. • argv[argc] is NULL.
예제: echoarg.c #include <stdio.h> // echoarg.c int main(int argc, char *argv[]) { int i; for (i = 0; i < argc; i++) /* echo all command-line args */ printf("argv[%d]: %s\n", i, argv[i]); exit(0); }
Environment Variables (1/2) • 환경 변수(environment variables)는 부모 프로세스에서 자식 프로세스로 전달된다. • 일반적으로, “.login” 또는 “.cshrc” 파일에서 환경 변수를 설정한다. • 환경변수 선언 형식: 이름=값 $ env USER=ysmoon LOGNAME=ysmoon HOME=/home/prof/ysmoon PATH=/bin:/usr/bin:/usr/local/bin:/usr/ccs/bin:/usr/ucb:/usr/openwin/bin:/etc:. SHELL=/bin/csh ... ...
Environment List (1/2) • 전역 변수 environ을 이용하여 환경 변수에 접근한다. • extern char ** environ; • 각 항목은 "환경 변수 이름=값" 의 형식을 가진다. • 각 문자열은 '\0'로 끝난다. • 환경 변수 리스트의 마지막은 NULL 포인터 • argv 와 같은 구조이다.
Environment List (2/2) environment strings environment pointer environment list environ: "USER=ysmoon" "LOGNAME=ysmoon" "HOME=/home/prof/ysmoon" "PATH=/bin:/usr/local…" "MAIL =/var/mail/ysmoon" ... "SHELL=/bin/csh" NULL
getenv() #include <stdlib.h> char *getenv(const char *name); Returns : pointer to value associated with name, NULL if not found • 환경 변수 리스트에서 이름이 name 인 것을 찾아서, • 해당 값(스트링)에 대한 포인터를 리턴한다. • 실패하면 NULL 포인터를 리턴
putenv() #include <stdlib.h> int putenv(const char *str); Returns: 0 if OK, nonzero on error • 환경 변수를 추가한다 • str은 "name=value" 형식의 문자열 • 성공적으로 실행된 경우 0을 리턴 • 같은 이름의 환경 변수가 이미 있다면 새 값으로 변경된다
setenv(), unsetenv() #include <stdlib.h> int setenv(const char *name, const char *value, int rewrite); Returns: 0 if OK, nonzero on error void unsetenv(const char *name); • setenv()는 환경 변수 “name = value”를 등록한다. • name 의 환경변수가 이미 있을 경우 • rewrite != 0 이면 새 값으로 변경되고, • rewrite == 0 이면 값이 변경되지 않는다. • unsetenv()는 환경 변수 “name”을 제거한다.
Env Manipulation Example (2/2) Why not change ???
Memory Layout of a C Program (1/2) high address command-line arguments and environment variables stack heap initialized to zero by exec uninitialized data (bss) initialized data read from program file by exec text low address
Memory Layout of a C Program (2/2) • Text Segment • Machine instructions (read-only, sharable) • Initialized Data Segment • e.g. int maxcount = 99; (initialized) • Uninitialized Data Segment • (bss: block started by symbol) • e.g. long sum[1000]; • Stack • automatic variables, temporary variables, return address, caller's environment (registers) • Heap • dynamic memory allocation (e.g., malloc())
Shared Libraries • Static Linking Library • 사용된 라이브러리 루틴들이(예: printf) 실행파일에 추가된다 • 실행파일 크기 증가 • Shared Library • 실행파일에 라이브러리 루틴들을 포함하지 않는다. • 공용의 메모리에 라이브러리 루틴을 로드하고 이를 공유한다. • 프로그램 크기 감소 • 처음 실행될 때 오버헤드 발생 (메모리에 Loading하는 과정이 필요할 수 있음) • 라이브러리가 Version-Up되어도 실행파일을 다시 컴파일 하지 않아도 됨
Memory Allocation (1/2) #include <stdlib.h> void *malloc(size_t size); void *calloc(size_t nobj, size_t size); void *realloc(void *ptr, size_t newsize); returns: nonnull pointer if OK, NULL on error void free(void *ptr); • Dynamic allocation of memory from heap • Provide suitable alignment • ex) doubles must start at the addresses that are multiples of 8.
Memory Allocation (2/2) • malloc() • allocates specified number of bytes (주어진 바이트 수를 할당) • initial value of memory is indeterminate (초기 값은 결정되지 않음) • calloc() • allocates specified number of objects of specified size(주어진 크기의 객체를 주어진 개수만큼 할당) • initialized to all 0 bits (초기 값은 0으로 결정) • realloc() • changes size of previously allocated memory (기 할당된 메모리 영역에 추가 할당) • initial value of new area is indeterminate (새 영역의 초기 값은 결정되지 않음)
예제: alloc.c #include <stdio.h> // alloc.c int main() { struct _cbuf { char buf[12]; } *cbuf; char *mbuf; if((mbuf = (char *)malloc(12)) == (char *)0) { perror("malloc():"); exit(-1); } strcpy(mbuf, "Kangwon"); if((cbuf = (struct _cbuf *)calloc(2, sizeof(struct _cbuf))) == (struct _cbuf *)0) { perror("calloc():"); exit(-1); } strcpy(cbuf->buf, " University"); if((mbuf = (char *)realloc(mbuf, 24)) == (char *)0) { perror("realloc():"); exit(-1); } strcat(mbuf, " National"); printf("%s%s\n", mbuf, cbuf); free(mbuf); free(cbuf); }