프로세스란?
- 컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램을 말한다.
- 우리가 코드를 짜서 만든 프로그램을 컴파일하여 실행시키면 실행되고 있는 프로그램은 하나의 프로세스가 된다.
- 우리가 일반적으로 짜는 프로그램은 단일 프로세스의 단일 스레드 프로그램이다.
- 만약 한 프로세스에서 다른 프로세스를 생성할 경우 생성된 프로세스를 자식 프로세스라 부르고 생성한 프로세스를 부모 프로세스라 부른다.
부모 프로세스로부터 상속받는 속성
- SUID 플래그와 SGID 플래그
- 현재 작업하고 있는 디렉토리
- 루트 디렉토리
- 파일 생성 마스크
- 시그널 마스크와 시그널 처리 설정
- 열린 file discriptor에 대하여 exec 호출 시 닫기(close-on-exec) 플래그
- 환경변수
- 부착된 공유 메모리 영역
- 메모리 매핑
- 자원 한계
부모 프로세르로부터 상속받지 않는 속성
- fork의 리턴값(부모는 0이 아닌 값, 자식은 0)
- 프로세스 ID
- 부모 프로세스 ID(생성된 프로세스는 자신을 생성한 프로세스의 ID가 부모 프로세스 ID로 설정된다.
- 자식 프로세스의 tims_utime(user코드를 실행하는데 사용된 cpu 시간), tms_stime(커널 코드를 실행하는데 사용된 cpu 시간), tms_cutime(child user 시간), tms_cstime(child의 커널 시간)은 모두 0으로 설정
- 부모가 잠근 파일 lock
- 아직 발동되지 않은 alarm 시그널은 자식에서 모두 해제
- 자식의 유보 중인 시그널 집합
함수
1. fork()
pid_t fork(void);
- 새로운 자식 프로세스를 생성할 때 사용하는 시스템 호출 함수이다.
- 한 번 호출에 두 개의 리턴 값을 리턴한다. 자식 프로세스에게는 , 부모에게는 자식 프로세스의 ID를 리턴한다.
- 프로세스 생성이 실패한 경우 -1을 리턴한다.
2. vfork()
pid_t vfork(void);
- fork()와 마찬가지로 자식 프로세스를 생성하는 함수이다.
- fork와의 차이점은 자식 프로세스가 먼저 실행됨을 보장한다는 것 이다. 따라서 생성된 프로세스가 exec계열 함수를 이용하여 새 프로그램으로 실행하는 경우에 주로 사용한다.
- vfork로 프로세스를 생성한 경우 exec계열 함수를 호출할 것으로 생각하므로 부모의 주소 영역을 참조하지 않을 것이라고 생각하여 부모 프로세스의 공간을 자식에게 복사하지 않는다.
- 복사하는 시간이 소요되지 않으므로 fork보다 약간의 성능 향상이 있다.
- 생성된 자식 프로세스는 exec계열 함수나 exit()을 호출할 때까지 부모 프로세스의 메모리 영역에서 실행되고 부모 프로세스는 자식 프로세스가 exec계열 함수나 exit()을 호출할 때까지 기다린다.
- 자식 프로세스가 좀비 프로세스가 되는 것을 최대한 방지하고 자식 프로세스가 항상 먼저 실행되는 것을 보장한다.
- 자식 프로세스를 종료할 때 _exit()을 이용하여야한다. 부모 프로세스의 표준 입출력 채널을 같이 사용하는데 자식 프로세스가 exit()을 호출할 경우 입출력 스트림을 모두 닫으므로 부모 프로세스에서는 입출력을 하지 못한다. 따라서 입출력 스트림을 정리하지 않고 종료시키는 _exit()을 사용해야 한다.
3. wait(), waitpid()
pid_wait(int *statloc);
pid_waitpid(pid_t pid, int *statloc, int options);
- 프로세스의 종료 상태를 회수하는 system call 함수이다.
- 자식 프로세스가 종료될 때까지 부모 프로세스가 기다리는 함수이다.
- 자식 프로세스가 언제 종료하는지 부모 프로세스는 알 지 못하므로 커널에서 시그널(SIGCHLD)을 보내 부모 프로세스에게 종료 사실을 알린다.
- 부모 프로세스는 시그널을 무시할 수도 있고 핸들러 함수를 등록하여 핸들러에게 규정된 동작을 수행하게 할 수 있다.
- statloc이 가리키는 곳에는 자식 프로세스의 종료 상태를 저장한다. 만약 자식 프로세스가 존재하지 않을 경우 -1을 리턴한다.
- 리턴 값은 종료된 프로세스의 pid값이다.
- waitpid의 pid값에 따라 기다리는 자식 프로세스가 달라진다.
- -1인 경우 임의의 자식 프로세스를 기다리며 wait()과 동일한 역할을 수행한다.
- 0보다 큰 경우 프로세스 id가 pid인 하나의 자식 프로세스를 기다린다.
- 0인 경우 프로세스 그룹 id가 호출한 프로세스와 동일한 임의의 자식 프로세스를 기다린다.
- -1보다 작은 경우 프로세스 그룹 id가 pid의 절대값과 같은 임의의 자식 프로세스를 기다린다.
- wait()은 가장 먼저 종료된 자식 프로세스 하나만을 기다린다. 만약 자식 프로세스가 없는 경우 에러를 리턴한다. 종료된 프로세스가 없는 경우 부모 프로세스는 자식 프로세스를 기다린다.
예제
자식 프로세스를 생성하여 자식 프로세스에서 1부터 10까지 출력하고 부모는 자식프로세스를 기다린 다음 1부터 10까지 출력하는 프로그램이다.
소스 코드
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid;
if((pid = fork()) < 0) { //에러인 경우
fprintf(stderr, "fork error\n");
exit(1);
}
else if(pid == 0) { //이 괄호 안은 자식이 실행
for(int i = 1; i <= 10; i++) {
printf("child : %d\n", i);
}
exit(0);
}
else { //여기부터 부모가 실행
if(waitpid(pid, NULL, 0) < 0) { //자식 프로세스가 끝날 때까지 기다림
fprintf(stderr, "wait pid error\n");
exit(1);
}
for(int i = 1; i <= 10; i++) { //부모 프로세스에서 1~10까지 출력
printf("parent : %d\n", i);
}
}
exit(0);
}
실행 결과
'리눅스 시스템 프로그래밍' 카테고리의 다른 글
[Linux] 리눅스 시스템 프로그래밍 사용자 아이디(user id) (0) | 2021.08.14 |
---|---|
[Linux] 리눅스 시스템 프로그래밍 exec 계열 함수 (0) | 2021.08.14 |
[Linux] 조건 변수(condition)와 mutex를 이용한 스레드 동기화(리눅스 시스템 프로그래밍) (0) | 2021.08.12 |
[Linux] Mutex를 이용하여 스레드(Thread) 동기화하기 (0) | 2021.08.11 |
[Linux] 리눅스 시스템 프로그래밍 thread(스레드) 생성과 종료 (0) | 2021.08.06 |