프로세스에 대한 연산
- 대부분 시스템 내의 프로세스들은 병행 실행될 수 있으며, 동적으로 생성되고, 제거되어야 한다.
→ 운영체제는 프로세스 생성 및 종료를 위한 기법을 제공해야 한다.
프로세스 생성
- 프로세스는 여러 개의 새로운 프로세스를 새로운 프로세스를 생성할 수 있다.
부모 프로세스
: 프로세스를 생성하는 프로세스자식 프로세스
: 생성된 새로운 프로세스- 자식 프로세스는 또다시 다른 프로세스를 생성할 수 있다.
- 부모와 자식 프로세스가 이어져 트리를 형성한다.
프로세스 식별자
프로세스 식별자(pid)
: 프로세스를 구분하는 데 사용하는 식별자
- 해당 식별자는 보통 정수
- UNIX, Linux 및 Windows와 같은 대부분의 현대 운영체제들이 사용
- pid는 시스템의 각 프로세스에 고유한 값을 가지도록 할당
- 이 식별자를 통해 커널이 유지하고 있는 프로세스 속성 탐색을 위한 색인으로 사용
- pid = 1 (
systemd 프로세스
)
- 모든 사용자 프로세스의 루트 부모 프로세스 역할을 수행
- 시스템이 부트 될 때 생성되는 첫 번째 사용자 프로세스
- 시스템이 부팅되면 다양한 사용자 프로세스를 생성
- 웹, 프린트 서버, ssh 등을 생성
- UNIX 시스템은 init 프로세스를 모든 자식 프로세스의 루트로 식별
- 최근 배포판에서는 systemd로 대체
부모와 자식 프로세스 간 자원 전달
- 자식 프로세스를 생성할 때, 작업을 하기 위한 자원이 필요
- 자원 : CPU 시간, 메모리, 파일, 입출력 장치 등
- 자식 프로세스가 자원을 얻는 방식
- 운영체제로부터 직접 얻는 방식
- 부모 프로세스가 가진 자원의 일부만을 사용하도록 제한
→ 자식 프로세스를 많이 만듦으로써 생기는 시스템 과부하를 방지
- 메모리나 파일과 같은 몇몇 자원들을 자식 프로세스와 공유
- 부모 프로세스의 자원을 분할하여 자식에게 나눠줌
- 부모 프로세스는 자식 프로세스에게 초기화 데이터를 전달할 수 있음
프로세스 실행
- 2가지 방식 존재
- 부모와 자식이 병행하게 실행을 계속함
- 부모는 자식이 실행을 종료할 때까지 기다림
- 자식 프로세스는 주소 공간 측면에서 볼 때 2가지 상태가 있을 수 있음
- 자식 프로세스는 부모와 똑같은 프로그램과 데이터를 가짐(복사본이라는 뜻)
- 자식 프로세스가 자신에게 적재될 새로운 프로그램을 가지고 있다.
- UNIX 운영체제에서의 프로세스 생성 및 실행
fork()
: 새로운 프로세스를 생성하는 시스템 콜- 새로운 프로세스는 원래 프로세스의 주소 공간의 복사본으로 구성
- 해당 기법은 부모 프로세스가 쉽게 자식 프로세스와 통신할 수 있게 함
- 해당 기법은 부모 프로세스가 쉽게 자식 프로세스와 통신할 수 있게 함
- 부모와 자식 프로세스는 fork() 명령어 후, 실행을 계속함
But, fork()의 반환값이 서로 다르다.
- 자식 프로세스의 fork() 반환값 → 0
- 부모 프로세스의 fork() 반환값 → 양수
- 새로운 프로세스는 원래 프로세스의 주소 공간의 복사본으로 구성
exec()
: 이진 파일을 메모리에 적재(load)하고 그 프로그램을 실행하는 시스템콜
- fork() 시스템 콜 다음에 둘 중 한 프로세스가 해당 시스템콜을 사용한다.
- exec()을 사용한 프로세스는 자신의 메모리 공간을 새로운 프로그램으로 교체한다.
- 프로세스의 주소 공간을 새 프로그램으로 덮어쓰기 때문에
오류가 발생하지 않는 한 제어를 반환하지 않는다.
fork()
→exec()
- 해당 작업을 통해 부모는 더 많은 자식을 생성할 수 있다.
- 자식이 실행되는 동안, 부모가 할 일이 없으면,
wait()
시스템 콜 호출
← 준비(ready) 큐에서 자신을 제거하기 위해
- 해당 작업을 통해 부모는 더 많은 자식을 생성할 수 있다.
프로세스 종료
- 프로세스를 종료하면 사용하던 자원은 운영체제를 되찾아간다.
wait()
: 자식 프로세스가 종료할 때까지 기다리는 시스템 콜- 부모가 자식의 종료 상태를 얻어낼 수 있도록 하나의 인자를 전달받음
- 부모가 어느 자식이 종료되었는지 구별할 수 있도록 종료된 자식의 프로세스 식별자를 반환
- 자발적 종료
exit()
: 운영체제에게 자신의 삭제를 요청하고 종료하는 시스템콜- 해당 시점에서, 프로세스는 자신의 부모 프로세스에게 상태 값을 반환할 수 있다.
wait()
시스템 콜을 통해 가능하다.- 상태값 → 정수값
- 프로세스의 모든 자원이 할당 해제되고 운영체제로 반납된다.
- 물리 메모리, 가상 메모리, 열린 파일, 입출력 버퍼 등을 포함한 자원
- 종종 종료 상태를 나타내는 인자를 전달받음
- 해당 시점에서, 프로세스는 자신의 부모 프로세스에게 상태 값을 반환할 수 있다.
- 비자발적 종료
- 부모 프로세스의 시스템콜 호출로 인해 종료되는 것
- 부모가 자식을 종료시키기 위해서는 자식의 pid를 알아야 한다.
- 자식 프로세스를 만들 때, 새 프로세스의 pid가 부모에게 전달됨
- 자식 프로세스를 만들 때, 새 프로세스의 pid가 부모에게 전달됨
- 부모가 자식을 종료시키기 위해서는 자식의 pid를 알아야 한다.
- 오작동으로 인해 다른 사용자의 프로세스를 임의로 중단(kill) 시키는 것
- 부모가 자식을 종료할 수 있는 경우
- 자식이 자신에게 할당된 자원을 초과 사용할 때
- 자식에게 할당된 작업이 더 이상 없을 때(필요 없을 때)
- 부모가 exit()하는데, 운영체제가 자식이 실행을 계속하는 것을 허용하지 않는 경우
- 부모 프로세스의 시스템콜 호출로 인해 종료되는 것
- 몇몇 시스템에서는 부모 프로세스가 종료한 이후에 자식 프로세스는 존재할 수 없다.
연쇄식 종료
: 정상적, 비정상적이든, 모든 자식 프로세스들은 종료되어야 한다.- 해당 작업은 운영체제가 실행
좀비 프로세스와 고아 프로세스
좀비 프로세스
: 종료되었지만 부모 프로세스가 아직 wait()를 호출하지 않은 프로세스- 종료하게 되면 모든 프로세스는 아주 짧은 순간 동안만 좀비 프로세스가 됨
- wait()를 호출하면 좀비 프로세스의 프로세스 식별자와 프로세스 테이블 항목이 운영체제에 반환
고아 프로세스
: 부모 프로세스가 자식 프로세스보다 먼저 종료될 때 발생- UNIX → 고아 프로세스의 새로운 부모 프로세스를 init 프로세스로 지정함으로써 이 문제를 해결
- init 프로세스는 주기적으로 wait()를 호출하여 고아 프로세스의 종료 상태를 수집
→ 프로세스 식별자와 프로세스 테이블 항목을 반환받음
- init 프로세스는 주기적으로 wait()를 호출하여 고아 프로세스의 종료 상태를 수집
- UNIX → 고아 프로세스의 새로운 부모 프로세스를 init 프로세스로 지정함으로써 이 문제를 해결