[TIL] 프로세스

river·2022년 6월 8일
0

스터디

목록 보기
2/9

프로세스

컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램.

프로세스는 실행 중인 프로그램으로, 디스크로부터 메모리에 적재되어 CPU 의 할당을 받을 수 있는 것을 말한다. 운영체제로부터 주소 공간, 파일, 메모리 등을 할당받으며 이것들을 총칭하여 프로세스라고 한다.
구체적으로 살펴보면 프로세스는 함수의 매개변수, 복귀 주소와 로컬 변수와 같은 임시 자료를 갖는 프로세스 스택과 전역 변수들을 수록하는 데이터 섹션을 포함한다. 또한 프로세스는 프로세스 실행 중에 동적으로 할당되는 메모리인 힙을 포함한다.

PCB(Process Control Block, 프로세스 제어 블록)

PCB 는 특정 프로세스에 대한 중요한 정보를 저장 하고 있는 운영체제의 자료구조이다. 운영체제는 프로세스를 관리하기 위해 프로세스의 생성과 동시에 고유한 PCB 를 생성 한다. 프로세스는 CPU 를 할당받아 작업을 처리하다가도 프로세스 전환이 발생하면 진행하던 작업을 저장하고 CPU 를 반환해야 하는데, 이때 작업의 진행 상황을 모두 PCB 에 저장하게 된다. 그리고 다시 CPU 를 할당받게 되면 PCB 에 저장되어있던 내용을 불러와 이전에 종료됐던 시점부터 다시 작업을 수행한다.

PCB 에 저장되는 정보

  • 프로세스 식별자(Process ID, PID) : 프로세스 식별번호
  • 프로세스 상태 : new, ready, running, waiting, terminated 등의 상태를 저장
  • 프로그램 카운터 : 프로세스가 다음에 실행할 명령어의 주소
  • CPU 레지스터
  • CPU 스케쥴링 정보 : 프로세스의 우선순위, 스케줄 큐에 대한 포인터 등
  • 메모리 관리 정보 : 페이지 테이블 또는 세그먼트 테이블 등과 같은 정보를 포함
  • 입출력 상태 정보 : 프로세스에 할당된 입출력 장치들과 열린 파일 목록
  • 어카운팅 정보 : 사용된 CPU 시간, 시간제한, 계정번호 등

프로세스의 상태

생성(create, new...)

  • 프로세스가 생성되는 중

실행(running)

  • 프로세스가 CPU를 차지, 명령어를 실행

준비(ready)

  • 프로세스가 CPU를 사용하고 있지는 않으나 다른 프로세스 실행을 위해서 일시적으로 정지해 있는, 언제든지 사용할 수 있는 상태. CPU가 할당되기를 기다리는 중이다. 일반적으로 준비 상태의 프로세스 중 우선순위가 높은 프로세스가 CPU를 할당받는다. CPU에 의해 처리되기 위해 주기억 장치에 존재하는 상태

대기(waiting)

  • 보류(block)라고도 한다. 프로세스가 입출력 완료, 시그널 수신 등 어떤 사건을 기다리고 있는 상태를 말한다.

종료(terminated)

  • 프로세스의 실행 종료

프로세스의 생성

먼저 부모 프로세스가 연산을 통해 자식 프로세스를 만든다. 생성된 자식 프로세스 또한 새 자식 프로세스를 만들 수 있으며, 이를 구별하기 위해 모든 프로세스는 각자 고유의 PID(Process ID)를 가진다. 이렇게 생성된 프로세스간의 관계는 하나의 큰 트리구조가 된다.

init 프로세스 : 리눅스, 유닉스 계열의 OS에서 최초로 실행되는 데몬 프로세스. PID는 항상 1이다.

생성된 자식 프로세스는 각자 고유의 PID, 메모리, CPU 등 새 PCB가 할당되며 고유의 자원을 획득한다. 이로 인해 부모 프로세스의 자원 접근에 제한이 생기고, 특수한 방법을 통해 공유할 수 있게 된다.

프로세스를 생성한 후 부모 프로세스는
1. 자식 프로세스가 종료될때까지 기다리거나(waiting queue),
2. 새로운 프로그램을 실행한다.

또한
1. 자식 프로세스가 부모 프로세스의 메모리 공간을 복제하거나,
2. 자식 프로세스가 새로운 메모리 공간에 load 되는
두가지의 메모리 로딩 방식이 존재한다.

fork()

fork()는 기존 프로세스와 동일한 프로세스를 복제하는 명령어이다. fork()로 복제된 프로세스가 바로 자식 프로세스이며, 이렇게 만들어진 부모 자식 프로세스는 동일한 리소스를 가지고 concurrently하게 동작하게 된다.

단, 복제된 부모 자식 프로세스간의 모든 PCB가 동일한 것은 아니며,
1. PID
2. 프로세스가 할당된 메모리 주소
3. 부모 프로세스의 PID를 가리키는 PPID
4. 프로세스를 구분하는 값인 CPID
는 다른 값을 가진다.

이렇게 나뉘어진 부모 자식 프로세스는 둘 중 어느 프로세스가 먼저 실행될지는 알 수 없으며, 위에 작성하였듯 랜덤하게, 우선순위가 높은 프로세스가 먼저 실행된다.

exec()

프로세스를 복제하는 fork()와는 달리 exec()는 본 프로세스는 그대로 둔 채, 본 프로세스가 담고 있는 내용만을 교체한다.
exec() 함수의 경우, 현재 프로세스가 완전히 새로운 프로그램을 실행하는 프로세스로 대체되기 때문에 반환값이 없다.

wait()

만약 부모 프로세스와 자식 프로세스가 동시에 실행되고 있는 상태에서 부모 프로세스가 먼저 종료되어버릴 경우, 큰 문제가 발생하게 되는데, 이럴 때 사용할 수 있는 system call이 wait()이다.

wait()은 자식 프로세스가 종료되기 전까지 부모 프로세스가 ready queue에서 대기하게끔 만든다. 자식 프로세스가 종료될 경우엔 반환값을 받고, 다시 동작하게끔 실행한다.
(성공적으로 자식 프로세스가 종료되었을 경우엔 자식 프로세스의 pid 값을, 실패했을 경우 -1을 리턴한다.)

프로세스의 종료

프로세스의 마지막 statement가 실행되거나, exit() 함수가 실행되면 프로세스가 종료되고, 모든 프로세스의 리소스가 해제된다.
보통 프로세스가 종료되는 과정은 부모 프로세스가 exit() 함수를 실행해 자식 프로세스를 종료시키는 방식이며, 이를 위해서는 자식 프로세스의 PID값이 필요하다. 이 때문에 프로세스를 생성할 경우 자식 프로세스의 PID값을 먼저 반환하는 것이다.

프로세스를 종료시키는 이유

  1. 자식 프로세스가 할당된 리소스 사용량을 초과했을 경우
  2. 자식 프로세스가 더 이상 필요가 없을때
  3. 부모 프로세스가 종료될때. (cascading termination)

고아 프로세스(Orphans process)

가끔 프로세스 종료가 정상적으로 동작하지 않아, 자식 프로세스가 실행중임에도 불구하고 부모 프로세스가 먼저 종료되어버린 상황을 말한다.

예를 들어 fork()를 통해 자식 프로세스가 생성되고, 프로세스의 PID값을 미처 받아오기도 전에 부모 프로세스가 종료되었을 경우, PID를 받아오기 위한 직계 부모 프로세스를 찾지 못해 최상위 프로세스인 init process의 PID 1을 반환한다.

반대 상황 또한 존재한다.

좀비 프로세스(Zombie process)

고아 프로세스와는 반대로 자식 프로세스가 자신의 PID값을 반환하지 않아, 자식 프로세스의 state를 회수하지 못한 부모 프로세스를 칭한다.

부모 프로세스는 자식 프로세스의 termination state 를 반환받아야 커널에서 자식 프로세스의 정보를 가지고 있는 구조체를 해제 시킬 수 있다.

profile
가보자고

0개의 댓글