컴퓨터 사이언스 (CS)/운영체제

03. 프로세스의 이해

한소희DE 2021. 6. 1. 01:14

목차

1. 프로세스란?

2. 멀티 프로세스란?

3. 프로그램의 메모리(Address) 구조

4. 프로세스의 생명주기

5. 프로세스 관리방법 (PCB, Context Switch)

6. 프로세스 Tree 관계 (Child, Parent)

 


 

1. 프로세스란?

프로세스란, 실행중인 프로그램을 뜻한다

하나의 프로세스가 실행되기 위해서는 자원이 필요하기 때문에, O/S는 프로세스를 관리해야 한다.

 


 

2. 멀티 프로세스란?

멀티프로세싱과 멀티태스킹을 가능하게 하는 것이 바로 운영체제의 핵심 기능이다.

(하지만 요즘은 멀티프로세싱이 아닌 멀티스레딩이 대세긴 한데, 이는 이후에 더 배울 것이다.)

 

2-1. 멀티프로세싱의 목적

Time Sharing 통해 동시에 여러 개의 프로세스를 실행시키는 것이다. 듬성듬성 수행되어도, CPU가 아주 빨라서 계속 멀티 작업하는 것 처럼 보인다.

유튜브는 영상은?

 

2-2. 멀티프로세싱의 이유

🔥 CPU의 사용 용량을 최대화하기 위해서다.

 


 

3. 프로그램의 메모리(Address) 구조

프로그램이 실행되면 프로세스가 생성되고, 메모리에 그 프로세스의 Address Space가 할당된다.
그것은 아래와 같은 섹션으로 구성된다.

  1. 텍스트(코드) 섹션
    1. 프로그램의 코드가 저장. 읽기만 가능
  2. 데이터 섹션
    1. 프로그램이 시작할때 생성, 종료 시 소멸되는 영역. 전역 변수나 배열 등이 저장됨. 초기화 데이터와 비초기화 데이터가 존재. 읽고 쓰기 가능
  3. Heap 섹션
    1. 실행시간동안 동적으로 사용되는 영역, delete 등에 의해 할당되거나 반환되는 영역
  4. Stack 섹션
    1. 지역변수 등이 저장되어 있는 임시 메모리. 함수 호출 시 생성되어 종료 시 반환. 읽고 쓰기 가능

Heap영역이 커지면 Stack 영역이 작아지게 되고, 역도 성립한다.

 

🔥 Code를 별도로 작성하는 이유

Code는 프로그램 생성 이후 바뀌지 않는다. 따라서, 한 프로그램이 여러 개의 프로세스로 실행되더라도 Code는 같다. 따라서 같은 프로그램의 프로세스면 Code를 공유해 메모리 사용량을 줄이기 위해 분리하여 작성한다.
🔥 Data, Stack 을 별도로 작성하는 이유

Stack은 함수의 내부에서만 저장되어 있으므로 특정 함수만, Data는 어떤 함수에서도 접근이 가능하기 때문에 분리해 관리하는 것이다.

 


 

4. 프로세스의 생명주기

 

 

  1. New - fetch 후 프로세스가 생성된 상태
  2. Running - CPU를 점유해 실행하는 상태
  3. Waiting - CPU에서 Time Sharing하게되어 다른 프로세스 들어와 다른 프로세스 실행하게 되면, (시간을 너무 오래쓰거나, 어떤 I/O 작업을 해야하거나, event wait 있으면) Waiting 상태가 됨
  4. Ready - Waiting 하다가(I/O 끝나거나 event wait 종료되면), Ready에 들어가서 다시 재실행 준비하는 상태
  5. Terminated - 종료

 

4-1. Queueing Diagram

위와 같은 프로세스를 큐잉 다이어그램으로 설명해보겠다.

  1. Ready queue에서 대기하던 것들이 FIFO로 running.
  2. I/O 요청 → Waiting(Interrupt)상태가 되어 I/O queue 에서 대기
  3. Interrupt → Ready queue → 대기 후 rerunning.
  4. 주어진 CPU Slice 모두 사용 후 Ready queue → 새로 할당 기다림
  5. exit() or return 등 종료에 의하여 terminated.

이때 OS는 문맥(PCB 정보)을 교환하는 역할을 수행한다. (아래 설명 참고)

 


 

5. 프로세스 관리방법

 

5-1. PCB (Process Control Block)

TCB ( Task ~) 라고도 한다. 각 프로세스 단위별로 정보를 Block 형태로, 가져야 하는 모든 정보를 이 곳에 저장한다. 그리고 운영체제는 이 PCB를 관리한다. 이 덕분에 Time Sharing 할 때도, 끊김없이 처리가 가능하다.

한 프로세스 당 한 개의 PCB가 존재한다.

  1. 프로세스의 상태 (어떤 생명주기인지)
  2. 프로그램 카운터 (프로세스가 다음에 실행할 명령어의 주소)
  3. CPU Register (IR, DR 포함)
  4. CPU Scheduling information - CPU 주고받기 위한 스케줄링 정보
  5. Memory 정보
  6. 계정 정보
  7. 어떤 User가 create한 프로세스인지 등
  8. I/O status information (내가 어떤 작업을 오픈했고, 어떤 자원을 오픈했는지 등)

※ 레지스터란? CPU가 요청을 처리하는 데에 필요한 데이터를 일시적으로 저장하는 기억장치

 

🔥 5-2. Context Switch

  1. 현재 프로세스 PCB 상태를 저장하고
  2. CPU 새 할당될 프로세스 문맥을 적재(읽)한다.

이러한 문맥 교환을 반복하며 Time Sharing 이 수행된다.

🔥 Context Switching 이 자주되면 좋은가?
 그렇지 않다. 스위칭 시 CPU는 아무 일을 할 수 없기 때문이다. 따라서 오버헤드 발생해 효율(성능) 떨어진다.

 


 

6. 프로세스 Tree 관계 (Child, Parent)

프로세스는 새로운 프로세스들을 생성할 수 있다. 이를 프로세스의 트리 관계라고 한다.

예시를 들어보겠다. init 프로세스(Parent)가 시작되면, 그 내부에 login이나 , sshd, bash 등의 프로세스(Child)가 트리 형태로 수행되어야 한다. 이때 새로운 프로세스(Child)의 생성은 fork 명령어를 활용하며, Child 프로세스의 결과값은 부모에게 돌려주며 종료된다는 특징이 있다. (더 자세한 건 다음 실습 포스팅을 참고하자!)

 

 

6-1. 실행가능성

이 Parent와 Child가 실행되는 경우는 두 가지 방법이 존재한다.

  1. Parent와 Child가 동시에 실행(Process)되는 경우
  2. Parent와 Child가 Wait 하며 실행

 

6-2. 주소 공간

만약, PCB를 parent에서 child로 넘어갔는데, 겹치는 업무가 존재한다면, 이들의 주소를 굳이 다르게 잡을 필요가 없다. 따라서 PCB만 별도로 두되, 주소 공간은 복제를 해서 child를 생성한다. (즉, parent와 child 주소는 같다.)

 

 

🔥 Parent와 Child 구분 방법?

PCB는 각각 ID가 존재하는데, 이를 pid라고 한다.

부모 프로세스는 pid 값이 양수이고,
자식 프로세스는 pid 값이 0이다.

 

6-3. 좀비와 오판

  • 좀비 프로세스: Child 프로세스 종료 후 Parent에게 정보 돌려주고, Parent가 그 정보를 받으면 Child는 삭제되기 마련인데, 그렇지 않고 계속 남아있는 경우를 좀비 프로세스라고 한다. 이는 Parent가 Child의 종료 정보를 제대로 처리하지 않아서 발생한다. 이는 용량을 차지할 수 있다. 그리고 이 좀비 프로세스가 종료되면 오판(고아) 프로세스가 된다. 따라서 부모는, 자식의 종료 정보를 확인하며 주기적으로 정리해주어야 한다.

 

  • 오판 프로세스: parent가 wait하지 않고 return 되어 종료되고, child 만 남은 프로세스. 원래 Child 프로세스는 종료 후 Parent로 돌아가는데, 그렇지 못한다.