Process에 관해 학습한 내용입니다.

Process

Background: program & process

program 생성 과정

→ program은 executable file이라고도 합니다.

  1. Source code 상태

    → .c file, .py file 등 프로그램이 수행하고자 하는 작업이 언어로 표현된 단계입니다. 흔히말하는 코드를 짠다고 할 때 우리가 작성하는 코드를 가리킵니다.

  2. Compile 단계

    → 우리가 작성한 source code를 기계어로 표현된 object file로 변환시켜주는 단계입니다. OS와 CPU에 따라 다른 형태의 파일을 만듭니다. 이를 ‘종속적이다’ 라고 말합니다.

  3. Object File

    → 이 자체로는 실행이 불가합니다. 프로세스로 변환되기 위한 정보가 필요합니다. 이러한 정보 중에는 절대적인 Memory address가 포함됩니다. Object file 자체는 relocatable address(=relative address)를 가집니다.

  4. Link 단계

    → 관련된 여러 오브젝트 파일들과 라이브러리들을 연결하여 메모리로 로드 될 수 있는 하나의 실행파일을 작성합니다.

  5. Executable File

    → 특정한 환경(OS)에서 수행될 수 있는 파일로 프로세스로의 변환을 위한 header, 작업 내용인 text, 필요한 데이터인 data를 포함합니다. 절대적인 주소로 표현되며 심볼들의 모든 주소가 절대값으로 표현됩니다.

Concepts & Definition

Process: A program in execution

(1) 정의

→ 자원 공유를 위한 추상적 개념으로 CPU 및 다른 자원을 공유하기 위한 단위입니다. 각 프로세스는 컴퓨터 자원을 독점하는 것으로 인식됩니다. 또한 각 프로세스 간 간섭과 침범이 불가능하다는 특징이 있습니다.

(2) Components

  • Context

    → 수행흐름을 뜻합니다. 한 프로세스에 여러 개의 실행흐름이 존재할 수 있으며 이를 ‘Threads’ 라고 말합니다.

    Threads 란?

    → 프로세스에서 실행 단위를 뜻하며 OS에서 context를 관리하기 위한 구체적 실체입니다. 각 Thread 마다 각각의 register와 Stack을 가지며 code, data, file들을 공유합니다. 즉, Process의 주소 공간(address space)를 공유합니다. 여러 Threads 구현 모델들이 있습니다.(single-thread, multi-thread 등)

  • Resources

    → 프로세스에 할당된 자원을 뜻합니다.

  • Storage
  • Network

Memory(Address space)

→ process가 할당받는 자원 중 가장 중요한 자원입니다.

Memory Structure

↑ 프로그램의 메모리 구조

↑ 프로그램의 메모리 구조

(1) Dynamic

→ process 실행 도중 변동이 있을 수 있습니다. Compile 시 적당량을 할당받으며 범위 내에서 사용이 가능합니다.

  1. Stack

    → LIFO 속성을 가진 자료구조 이며, pop과 push 연산을 사용합니다. 꼭대기를 가리킬 Top pointer가 필요합니다. 일시적인 data(함수 매개변수, 리턴 주소, 지역 변수 등)을 저장합니다. 시스템에 따라 최대 크기가 제한되지만 변경 가능합니다.

  2. Heap

    → 동적 할당을 위한 주소 공간입니다.

(2) Static

→ 소스코드에서 읽힌 코드와 전역변수를 저장합니다. Compile 시 크기가 결정되며 변동이 없습니다.

  1. Data

    → 전역 변수와 data를 저장합니다.

  2. Text

    → program 소스 코드를 저장합니다.

Process: Similar nouns

Process와 혼동되는 유사 용어

  1. Job → Batch system
  2. Program → 실행되기 전의 프로그램 이미지
  3. Task → 일반적 의미로 Job과 유사
  4. Thread → 프로세스의 실행 단위
  5. Processor → CPU 프로세서

Context Switch

→ address space 변환 이라고도 합니다.

정의

→ CPU(Processor)가 프로세스를 교체할 때 일어납니다. 이전 작업 상태를 PCB에 저장하고 새로운 작업을 수행하기 위해 정보를 로드합니다. 이 작업들이 수행되는 동안 CPU는 Idle 상태이며 이것이 Context Switch의 Overhead가 됩니다. 단, CPU의 Architecture에 따라 차이가 있습니다.

CPU Architecture

  1. CISC

→ 많은 명령어를 가지며 복잡한 회로를 가집니다. 물리적인 공간을 차지하지만 레지스터의 용량이 적습니다.

  1. RISC

    → 많은 레지스터를 가지며 context switch시에 레지스터 내용 변경에 대한 overhead가 비교적 큽니다.

Thread Switching과 같나요?

→ Thread Switching은 같은 process 위에서 동작하기 때문에 별도의 주소공간 변경이 필요하지 않습니다. 이는 TLB(Translation Lookaside Buffer) Cache flush를 요구하지 않게 됩니다.

TLB(Translaction Lookaside Buffer)

→ MMU(Memory Management Unit)의 한 부분입니다. MMU 자체는 논리주소를 물리주소로 바꿔주는 역할을 하는데 이때 필요한 정보들이 담겨있는 공간이 TLB입니다. Context switching이 발생할 때마다 이전 process의 공간에 침범을 방지하기 위해 TLB를 초기화 해줘야하며, 이후 다시 MMU로부터 process와 연관된 memory location을 불러옵니다. 이러한 행위들로 인해 ‘Overhead’가 발생됩니다.

State Diagram

Untitled

↑ Process State diagram

1. New

→ 새로운 process를 생성합니다.

2. Ready

→ 프로세스가 프로세서의 배정을 대기하는 상태입니다.

3. Running

→ 프로그램이 실행 중인 상태입니다.

4. Waiting

→ I/O 처리를 기다리거나 다른 event 처리를 기다리는 중 입니다.

5. Terminated

→ 실행이 모두 끝나고 종료하는 단계입니다.

Process creation & termination

create? fork()?

→ create은 ‘무’ → ‘유’ 를 만드는 것입니다. 하지만 보통 Linux에서는 fork()라는 system call을 이용하여 ‘parent’ process에서 ‘child’ process를 파생시킵니다. 이 경우, 자식 프로세스는 부모 프로세스의 주소 공간(Address space)를 복제하여 사용합니다. windows의 경우 아예 새로운 프로세스를 만들며 가장 필수적인 두 가지의 요소가 IpApplicationName과 IpCommandLine 입니다.

Process creation

  • 일반적으로 프로세스는 자신만의 고유한 Process ID (PID)를 가집니다.
  • 부모 프로세스와 자식 프로세스 간 자원을 공유하는 Option들이 존재합니다.
    • 모든 자원 공유
    • 부모의 자원 중 일부를 공유
    • 부모와 자식 간 자원 공유를 하지 않는 경우
  • 또한 부모 프로세스와 자식 프로세스 간에 실행 Option도 존재합니다.
    • 동시 실행
    • 자식이 종료하고 난 뒤 부모 재개

Process termination

→ 프로세스가 자신에게 할당된 자원을 모두 버리는 것을 뜻합니다. exit() system_call에 의해 진행됩니다.

Zombie process

→ 부모 프로세스는 자식 프로세스가 종료되었다는 call을 듣기 전까지 wait() system_call에 의해 대기 상태가 됩니다. 이때 wait() system_call이 바로 실행되지 않기 때문에 child가 죽는 terminate이 진행된 후 parent의 wait()가 실행되기 전까지 child를 ‘완전히 죽지 않은’, 즉 좀비 프로세스라고 표현합니다.

Orphan process

→ 이 경우 부모 프로세스가 wait() 단계를 거치지 않고 먼저 종료된 것을 뜻합니다. 이 경우 child는 orphan(고아)가 됩니다.

맨 위로 이동 ↑