[번외] 리눅스 프로세스 동작 방식
리눅스에서 프로세스는 명령어 입력부터 종료까지 일련의 시스템 호출과 상태 변화를 거친다. 이 장에서는 프로세스의 생성과 실행 과정을 다룬다.
1. 프로세스 생명 주기
1.1 프로세스 생성 (fork
)
fork
시스템 호출을 통해 자식 프로세스를 생성한다.- 자식 프로세스는 부모의 복사본이며, 별도의 PID를 가진다.
- 부모와 자식은 이후 독립적으로 실행된다.
1.2 프로그램 실행 (exec
)
exec
시스템 호출은 현재 프로세스를 지정한 프로그램으로 덮어쓴다.- 메모리, 코드, 스택 등이 모두 대체되며, 이전 실행 내용은 사라진다.
1.3 상태 변화
상태 | 설명 |
---|---|
실행(Running) | CPU를 점유하여 실행 중인 상태 |
준비(Ready) | 실행 대기 중, CPU 할당을 기다리는 상태 |
대기(Waiting) | 이벤트(I/O, 신호 등)를 기다리는 상태 |
종료(Terminated) | 실행을 마치고 종료된 상태 |
1.4 프로세스 대기 (wait
)
- 부모 프로세스는
wait
호출로 자식 프로세스 종료를 기다린다. - 자식의 종료 코드가 부모에게 전달된다.
1.5 입출력 처리
- 표준 입력(stdin), 표준 출력(stdout), 표준 오류(stderr)를 통해 입출력을 수행한다.
- 파일, 터미널, 네트워크 등 다양한 자원과 연결될 수 있다.
1.6 프로세스 종료 (exit
)
- 프로세스는
exit
호출을 통해 종료한다. - 시스템에 종료 상태를 반환하고, 자원을 해제한다.
2. 셸 명령어 실행 과정
사용자가 셸에 명령어를 입력했을 때, 내부적으로 다음과 같은 흐름으로 실행된다.
2.1 명령어 입력
ls -l
사용자가 터미널에 명령어를 입력하고 엔터를 누른다.
2.2 명령어 해석
- 셸은 명령어를 분석하고 명령(command)과 인자(arguments)를 분리한다.
command: ls
arguments: -l
2.3 프로세스 생성
- 셸은
fork()
를 호출하여 자식 프로세스를 생성한다.
pid_t pid = fork();
2.4 프로그램 실행
- 자식 프로세스는
exec()
를 호출하여 실행할 명령어로 자신의 메모리를 덮어쓴다.
if (pid == 0) {
execl("/bin/ls", "ls", "-l", (char *)NULL);
}
2.5 부모 프로세스 대기
- 셸은
wait()
또는waitpid()
로 자식 프로세스 종료를 대기한다.
int status;
waitpid(pid, &status, 0);
2.6 결과 출력
- 실행된 명령어의 결과가 표준 출력(stdout)을 통해 터미널에 출력된다.
3. 셸 스크립트 실행 과정
3.1 스크립트 실행
./myscript.sh
- 셸은 파일을 열고 첫 줄부터 한 줄씩 해석하여 명령어를 실행한다.
3.2 명령어 실행
- 스크립트 내부 명령어는 개별적으로
fork
-exec
를 통해 실행되거나, 셸 내에서 직접 실행된다.
3.3 실행 결과 출력 및 종료 대기
- 각 명령어의 결과는 출력되고, 셸은 명령어 실행이 끝날 때까지
wait
로 대기할 수 있다.
요약
개념 | 설명 |
---|---|
fork | 부모 프로세스로부터 자식 프로세스를 생성 |
exec | 자식 프로세스가 다른 프로그램으로 대체됨 |
wait | 부모가 자식 종료를 기다림 |
exit | 프로세스 종료 |
표준 입출력 | stdin, stdout, stderr 등을 통해 처리됨 |