본문 바로가기

Computer Science/OS

2-1. Virtualization: 프로세스 관리와 자료구조, Process API

프로세스 관리와 자료구조, Process API

프로세스 가상화

Process(프로세스)실행 중인 프로그램으로 정의한다.

  • Program이 디스크 상에 존재하는 명령어와 정적 데이터의 묶음이라면(Passive),
  • Process는 program counter가 있는 동적인 존재이다(Active).

실행 가능한 파일을 memory에 load하여 program이 process가 된다.

→ 하나의 프로그램이 여러 프로세스를 생성할 수 있다.

Process는 Code section / Data section / Stack / Heap / Program counter로 이루어진다.

Process 구조
이 구조대로 process가 돌아간다.

OS는 Virtualization으로 CPU가 여러 개인 듯한 illusion(착각;환영)을 만들어낸다. (Time Sharing; 시분할)

Context switching
Context Switching: Scheduling Policy로 결정

Process의 Machine State

  • Address space: 접근 가능 memory
  • Program counter: 어느 명령어가 실행 중인지
  • Stack Pointer, Frame Pointer: 함수 변수, return 주소 Stack.
  • 입출력 정보

Process API

모든 현대 운영체제에서 제공되는 API는 다음과 같다:

  • Create: 새로운 process 생성
  • Destroy: 프로세스 종료
  • Wait: 프로세스의 실행 중지 기다림
  • 각종 제어: 프로세스 일시정지, 재개 등
  • 상태: 프로세스 상태 정보 얻기

Process 생성

Process 생성 과정

  1. Program code, Static data를 memory에 load
  2. 지역 변수, arguments, return address 저장 Stack 할당 (`main()`의 `argc`, `argv`)
  3. 동적 할당 data (`malloc()`, `free()`) 저장 Heap 할당
  4. I/O Setup: `STDIN(0)`, `STDOUT(1)`, `STDERR(2)` File Descriptor
  5. Entry point에서 program 실행: CPU를 새 process에 넘긴다.

Process State

프로세스는 기본적으로 다음 세 상태 중 하나에 존재할 수 있다.

  1. Ready: Memory에 올라와 CPU 사용이 준비되었지만 다른 process 실행 등의 이유로 대기 중인 process
  2. Running: Scheduling algorithm에 따라 뽑혀 실행 중인 프로세스들.
  3. Blocked: I/O 요청 등을 process가 기다리는 동안 수행을 중단시킨 상태.
    그 동안 ready 중이었던 다른 process가 실행된다.
    Process State transition diagram
    Transition Diagram
    Process State Transition 과정 예시
    Process State Transition 과정 예시

자료구조

  • PCB(Process Control Block): 프로세스 관리 위한 자료구조로, 프로세스 하나당 하나씩 존재
    PCB
    PCB
  • Process List(Queue): Ready / Blocked / Running process들에 대한 list
    ex) Ready에 있는 process의 PCB를 queue로 만들어서 관리: ready queue.
    Process List
    Process List
  • Register Context: 운영체제가 관리하는 프로세스 정보;
    이 register 값들을 복원해 프로세스 실행을 재개한다. (Context switching)
    xv6 Kernel에서 OS가 각 프로세스를 추적하는데 필요한 정보
    xv6 Kernel에서 OS가 각 프로세스를 추적하는데 필요한 정보

Process API

Process는 `pid`로 구분, 관리된다. 부모 프로세스는 자식 프로세스를 만들고,... 반복: 트리 모양을 이룬다.

Process tree
Process tree

fork()

system call로 자식 프로세스를 만든다.
부모 process의 주소 공간의 copy를 가지는데, 반환 값이 다르다. (부모: 자식 pid, 자식: 0)
자식 프로세스는 자신의 주소 공간, 레지스터, PC 값을 가진다.

wait() / waitpid()

`wait(&status)` system call은 자식 프로세스로 하여금 종료될 때 부모 프로세스에게 exit status를 전달하는 역할을 한다.
exit status는 "process table"에 저장이 되고 process table entry는 부모 프로세스가 `wait()`한 이후 할당 해제된다.
→ 만약 부모 프로세스가 `wait()`를 수행하지 못하면, 자식 프로세스의 process table 값이 그대로 남아 있게 되고, 이는 zombie process를 만들게 된다.

Reaping 과정은 부모 프로세스가 `wait()`나 `waitpid()`를 통해 process table에서 zombie 자식을 없애는 방법으로 수행된다.

부모 프로세스가 wait()로 자식 reap
부모 프로세스가 wait()로 자식 reap

Zombie vs. Orphan 프로세스

  • zombie 프로세스는 실행이 종료되었으나 process table에 아직 항목이 존재하는 프로세스이다.
    → 모든 프로세스는 잠깐동안, zombie 프로세스로 존재할 수 있다.
  • 만약 부모 프로세스가 wait를 수행하지 않고 그대로 종료해버린다면, 그 자식 프로세스들은 orphan 프로세스가 된다. (아직 실행 중)
    → init 프로세스가 이 프로세스들의 새로운 부모가 된다.
    • init 프로세스는 주기적으로 `wait()`해서 입양아들을 떨궈 낸다.
    • ∴ 부모는 죽었지만, 자식이 계속 실행중인 경우.

zombie, orphan process 예시

exec()

이 system call은 자기 자신이 아닌 다른 프로그램을 실행해야 될 때 사용한다.
OS는 새 프로그램을 위해 heap과 stack, 주소 공간을 새로 초기화한다.
두 개의 인자: 실행 파일의 이름과 인자들의 배열이 주어지면 해당 실행 파일의 코드와 정적 데이터를 읽어들여 현재 실행 중인 프로세스의 코드 segment와 정적 데이터 부분을 덮어쓴다. (현재 프로그램을 다른 프로그램으로 대체)

fork()와 exec()를 분리하는 이유는?

fork()와 exec()를 따로 실행시킴으로써, I/O redirection과 pipe와 같이 다양한 설정을 할 수 있다.

  • I/O redirection: `cat w3.c > newfile.txt`
  • Pipe: `echo hello world | wc`