process, task 혼용
- 살아 움직이는 프로그램을 의미
- 디스크에서만 존재하던 프로그램 및 데이터가 메모리로 올라오면서 생성
프로세스와 관련된 시스템 콜
- fork(), clone() : 프로세스 생성 task_struct 생성
- execve() : excute a new program(loading) → 디스크에서 메모리로 데이터를 옮기는 과정
- 컴파일 된 프로그램을 실행할 때 사용되는 시스템의 구성요소 중 하나인 loader의 역할과 유사
- 해당 함수는 새로운 프로그램의 실행 가능한 파일을 메모리로 로드하고, 그 파일을 실행할 새로운 프로세스 생성
- execve()를 호출하면 현재 프로세스의 메모리 이미지(txt, data, stack,heap..)가 새로운 프로그램의 코드와 데이터로 대체 → 로더가 하는 일과 유사한 작업
- 해당 시스템 콜은 로더보다 더 높은 수준에서 작동
- 로더는 실행파일을 로드하고 초기화하는데 필요한 모든 단계를 수행하지만 execve()의 경우 이미 로드된 프로그램 이미지에 새로운 프로그램의 이미지를 덮어쓰는 역할
- 프로세스 내에 메모리 이미지의 완전한 대체를 의미하는데, 로더의 경우 프로그램을 초기화하고 시작하기 전에 현재 프로세스의 상태를 보존하고 다시 복구하는 작업도 포함함
- loader의 역할을 포함하며, 기존 프로세스를 새로운 프로그램으로 교체하고 실행할 수 있게해줌
- exit() : 프로세스 종료 및 부모 프로세스에게 자식 프로세스의 상태값을 알려줌
- wait(), waitpid() : 진행 중이던 프로세스를 지정된, 혹은 다른 프로세스가 종료가 될 때까지 대기 상태로 변환
- getpid() : process ID를 가져옴
- getppid() : parent의 pid를 가져옴
ex:
write와 printf
- 해당 함수를 통해 데이터를 터미널에 출력하면 두 함수 모두 터미널에 내용이 작성
- 터미널 화면에 텍스트나 데이터를 표시
- 차이점 (출력형식, 표준출력, 편의성)
- write
- 데이터를 바이트 단위로 출력
- 주로 이진 데이터 혹은 형식화되지 않은 텍스트 데이터를 출력하는데 사용
- 파일 디스크립터를 직접 지정(ex : STDOUT_FILENO)를 사용하여 표준 출력 스트림에 데이터를 쓸 수 있다
- printf
- 형식화 된 문자열을 출력할 때 사용
- 형식 지정자를 사용하여 출력 형식 지정 → 변수나 상수 값을 포맷에 따라 문자열로 변환하여 출력
- 표준 출력 스트림(stdout)에 자동으로 출력→별도의 파일 디스크립터 지정할 필요 x
- write
- write 더 낮은 수준의 출력을 다루며, printf 더 높은 수준의 형식화된 출력을 다루는데 사용
동작 원리
fork()
- 메모리 이미지가 동일한 프로세스를 하나 더 만든다
- 기존의 부모 프로세스는 유지하며 새로운 자식 프로세스를 만든다.
- 그렇기에 프로그램의 제어의 흐름이 나눠지게 된다
- 부모의 흐름과 자식의 흐름(시스템 관점)
- return 값이 두개가 된다.
- fork의 경우 부모와 자식이 다른 리턴값을 가지고 있음
- (부모는 자식의 pid를 리턴 값으로 가지며, 자식은 0을 반환)
- 대체로 자식의 pid는 부모보다 크다
- fork의 경우 부모와 자식이 다른 리턴값을 가지고 있음
- 그렇기에 프로그램의 제어의 흐름이 나눠지게 된다
- 프로세스는 독립적 개체이므로 서로의 자원을 공유할 수 없다.
- 전역, 지역변수와 상관없이 부모와 자식 프로세스간에도 자원의 공유는 불가하기에 자식에서 변화된 변수의 값은 부모에서는 간섭하지 못한다.,
- 수정이 되는 data와 stack의 경우 복사가 되서 자식 프로세스에게 할당이 된다
- 그렇지만 수정이 불가능한 text 부분은 부모와 자식이 같이 사용한다.
- 이때 보여지는 memory 부분의 이미지 나열에서 기존에 배운 text - data - heap - stack으로 나열된 부분들은 가상의 이미지이며 실제로는 여러 프로세스의 이미지들이 섞여있는 형태로 존재한다
- 전역, 지역변수와 상관없이 부모와 자식 프로세스간에도 자원의 공유는 불가하기에 자식에서 변화된 변수의 값은 부모에서는 간섭하지 못한다.,
execve()
- 현재 프로세스의 메모리 이미지(text, data, stack, heap)을 새로운 바이너리 코드로 변경
int execlp(const char *filename, const char *arg0, ..., const char argn, (char *) 0); int execvp(const char *filename, char *const argvl 1); 30147146 int execl(const char *pathname, const char *arg0, .., const char *argn, (char *) 0); int execv(const char *pathname, char *const argv[ ]); int execle(const char *pathname, const char *arg0, ..., const char *argn, (char *) 0, char *const envp[ ]); int execve(const char *pathname, char *const argv[ ], char *const envp[ ]);
- filename : 파일의 이름만을 나타냄
- pathname : 파일의 정확한 경로만 나타냄
- envp : 환경변수를 나타내는 배열
- 프로세스가 실행될 때 사용할 수 있는 정보를 담고 있는 변수들의 집합
- 프로세스가 실행될 때 환경을 설정하고 커맨드 라인 프로그램이 이 정보를 사용할 수 있게 함
- 각각의 문자열을 “이름 = 값” 형식을 가짐 (ex : "PATH=/bin:/usr/bin”)
- 만약 해당 변수가 없는 메서드의 경우 호출되는 프로세스의 환경변수를 상속받아 사용
- -l : list를 의미
- -v : vector를 의미
- list의 형태를 가진 인자들을 모아서 argv[]에 모아서 받음, 표현의 차이이며 실제로 결과는 동일하다.