본문 바로가기

기본/운영체제

[OS] CPU 가상화 (CPU Virtualization): 1. 프로세스란

 

*이 글은 Operating Systems: Three Easy Pieces(운영체제 아주 쉬운 세 가지 이야기)를 바탕으로 작성되었습니다. 첨부한 모든 그림은 해당 도서에서 가져온 자료입니다. 내용 중 잘못된 부분이 있다면 알려주세요 :)

 

 

우리는 여러 프로그램동시에 실행하길 원한다.

 

운영체제는 여러 프로그램들이 실행되는 것처럼 환상을 만들어(CPU를 가상화), 이를 가능하게 만든다.

 

이 과정에서의 운영체제의 핵심 개념 중 하나는 프로세스이다.

프로세스현재 실행 중인 프로그램으로 정의된다.

 

하나의 프로세스를 실행하고, 중단하고 다른 프로세스를 scheduling하여 실행을 반복하며, 실제로 여러 프로그램이 실행되고 있다고 느끼게 만든다.

이를 time-sharing이라고 하며, 하나의 프로세스를 중단하고 다른 프로세스를 실행하는 것을 context switch라고 한다.

 


🧐 Process란 무엇인가

 

위에서 말했듯이

process는 실행 중인 program이다.

 

 

특정한 순간의 프로세스를 표현하기 위해선, 실행되는 동안 접근했거나 영향받은 자원의 목록을 보면 된다.

이 프로세스의 구성요소를 이해하기 위해선 하드웨어 상태(machine state)를 이해해야 한다.

프로그램이 실행될 동안 읽거나 업데이트 할 수 있는 하드웨어 영역은 Memory, Register이다.

 

Memory

  • 프로세스의 하드웨어 상태 중 가장 중요한 요소
  • 명령어, 실행 프로그램이 읽고 쓰는 데이터는 메모리에 저장된다.

 

Register

  • program counter(PC): 프로그램의 어느 명령어가 실행 중인지 알려줌
  • stack pointer, frame pointer: 함수의 변수와 리턴 주소를 저장하는 스택 관리

 


 

🧐 Program 대략적인 실행 과정

 

프로그램이 어떻게 프로세스가 되는가?

그 과정을 살펴보자.

 

 



 

  1. 프로그램 code, static data를 메모리(process의 address space 위치)에 로딩
  2. OS가 stack, heap을 위한 영역 할당, 초기화
  3. 입출력과 관계된 초기화 작업 수행
  4. main() 루틴으로 분기함으로써 CPU를 새로 생성된 프로세스에게 넘김

 

 

 

 

 

 

 


🧐 Process의 상태

 

 

 

 

  • 실행 (Running): 실행 중인 프로세스 
  • 준비 (Ready): 실행 준비가 된 프로세스, 다른 프로세스를 실행 중 등의 이유로 대기 중
  • 대기 (Blocked): 사건을 기다리는 동안 수행 중단 중인 프로세스

 

 

 

 

 

두 개의 프로세스를 실행한다고 가정하고 예를 살펴보자.

 

Process0이 Running 상태로 실행되는 동안 Process1은 Ready 상태이고, 끝난 뒤 Process1이 Running 상태로 변한다.

 

I/O도 고려하여 생각해보자

 

 

Process0이 Running 상태로 실행되다가 입출력을 요청하여 Blocked 상태가 되고, Ready였던 Process1이 싱행되게 된다.

입출력 입력 받으면 Process1은 Ready 상태로 변하고, Process1이 끝난 뒤 다시 실행된다.

 

 

위 예시의 상황에서 Process0, Process1을 언제, 어떤 순서로 실행할지 결정은 성능이 큰 영향을 미친다.

이 결정을 내리는 것이 바로 스케줄러이다. (추후 배우는 내용,,)

 


🧐 Process의 자료구조

 

 

위는 xv6 커널에서의 프로세스 구조이다.

(xv6는 교육용 커널로, 실제 Linux, Mac OS, Window 등은 더 복잡하다고 합니다...!)

 

  • register context
struct context {
	int eip;
    int esp;
    int ebx;
    int ecx;
    int edx;
    int esi;
    int edi;
    int ebp;
};

- 프로세스가 중단되었을 때 해당 프로세스의 레지스터 값들을 저장한다.

- 이 레지스터 값들을 복원하여, 운영체제는 프로세스 실행을 재개한다.
    => context switch

  • process state
enum proc_state {UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE}

(OS마다 조금씩 상태가 다르다고 합니다)

 

  • process info
    • PCB(Process Control Block)
struct proc {
	char *mem;  //프로세스 메모리 시작 주소
    uint sz;   // 프로세스 메모리의 크기
    char *kstack;   // 이 프로세스의 커널 스택의 바닥 주소
    enum proc_state state;  // 프로세스 상태
    int pid;   // 프로세스 id
    struct proc *parent;   // 부모 프로세스
    void *chan;  // 0이 아니면, chan에서 수면
    int killed;   // 0이 아니면, 종료
    struct file *ofile[NOFILE];   // 열린 파일
    struct inode *cwd;   // 현재 디렉토리
    struct context context;   // 프로세스를 실행시키려면 교환
    struct trapframe *tf;   // 현재 인터럽트에 해당하는 trapframe
};

 

 

 


 

이번 글은 사실상 CPU 가상화를 알기위해

process의 개념을 다져본 것이고, 진짜는 다음부터!

 

더 구체적으로 프로세스 구현과 위에서 언급했던 스케줄링에 대해 차차 알아보자.