-
[OS] 운영체제의 추상화: 프로세스와 CPU 가상화CS/OS 2025. 9. 9. 20:30
Three Fundalmental Pieces
일반적으로 운영체제의 세 축은 CPU/메모리/디스크 자원의 가상화(Virtualization), 동시성(Concurrency), 영속성(Persistence) 으로 설명할 수 있습니다.
여기서 오늘은 Virtualization에 대해서 이야기하겠습니다.
Virtualization이란?
운영체제에서 가상화(Virtualization)란 하나의 물리적 자원을 여러 개의 논리적 자원처럼 보이게 하는 추상화 기법을 의미합니다. 대표적으로 CPU 가상화를 통해, 단 하나의 CPU(또는 소수의 코어)로도 수십~수백 개의 프로세스가 동시에 실행되는 것처럼 보이게 합니다. 이는 실제로는 운영체제가 각 프로세스에 짧은 시간 단위로 CPU를 번갈아 할당(Time-sharing)하기 때문에 가능한 일입니다.
예를 들어
- 웹 브라우저, 게임, 메신저 등 다양한 프로그램을 동시에 실행할 때
- CPU 걱정없이 수백개의 프로세스를 동시에 실행할 때
이것은 OS가 CPU를 Virtualize하고 프로세스들이 CPU를 효율적으로 공유하기 때문에 가능합니다.
Process란?
실행 중인 프로그램의 인스턴스이자 CPU뿐 아니라 실행 중인 프로그램의 전체 상태(코드, 데이터, 자원, 레지스터 값 등)를 추상화한 개념 단위입니다.
- 실행단위
- 스케쥴링 단위
- job, task
프로세스는 실행 중인 프로그램의 단위입니다.
여기서 프로그램은 정적인 파일을 의미하고, 프로세스는 프로그램을 실행해서 메모리(RAM)에 올라간 실행 단위를 뜻합니다.
즉, 하나의 프로그램으로 다양한 프로세스를 생성할 수 있습니다. (One-to-Many 관계)
그러면 어떻게 OS가 Processes를 다룰까?
과거에는 하나의 프로세스가 처음부터 완료될 때 까지 실행하는 Uniprogramming(단일 작업) 방식을 사용했습니다.
→ 이런 방식에는 하드웨어 활용성이 낮다는 문제가 발생합니다.
예를 들어, I/O 작업과 같은 프로세스가 기다리는것에 많은 시간을 소비한다면 결론적으로 CPU 낭비가 발생합니다.
따라서 현대의 OS는 Multiprogramming(다중 작업)방식을 사용합니다.
한 개의 프로세스가 I/O작업 등으로 blocked이 된다면 다른 프로세스를 CPU에서 실행하는 방식입니다.
이렇게하면 효율성 & 속도면에서 이점이 있습니다.
Process의 구성
프로세스는 프로그램 실행에 관한 모든 상태를 포함하고 있습니다.
- address space
- 프로그램 실행 코드
- 프로그램 실행 데이터
- 실행 stack
- Program counter (PC)
- registers

*여기서 PC(program counter)는 다음 지시를 가리킵니다.
각 프로세스는 머신에 대한 고유한 관점을 가지고 있습니다.
- own address space
- own virtual CPU
- own open files
Process의 실행과정
1. 코드 및 데이터 로드합니다.
프로그램 실행의 첫 번째 단계는 디스크에 저장되어 있는 프로그램의 코드와 정적 데이터를 메모리에 올리는 것입니다. 예전 운영체제들은 프로그램을 실행하기 전에 모든 내용을 한꺼번에 메모리에 올렸지만, 요즘 운영체제들은 필요한 부분만 그때그때 메모리에 올리는 '게으른(lazy)' 방식을 사용해 효율성을 높입니다.
2. 스택 영역 할당
운영체제는 프로그램이 사용할 스택(Stack) 메모리 공간을 할당합니다. 스택은 함수가 호출될 때 사용되는 지역 변수, 함수 매개변수, 그리고 함수가 끝난 후 돌아갈 주소 등을 저장하는 데 쓰입니다. 운영체제는 main() 함수의 argc와 argv 같은 초기 인자들을 이 스택에 넣어 준비합니다.
3. 힙 영역 할당
다음으로, 프로그램이 실행 중에 동적으로 메모리를 할당받을 수 있도록 힙(Heap) 메모리 공간을 할당합니다. malloc()과 같은 함수를 통해 필요한 만큼 메모리를 요청할 때 이 힙 영역이 사용됩니다.
4. 입출력(I/O) 초기화
운영체제는 입출력 관련 초기화 작업을 수행합니다. 예를 들어, UNIX 시스템에서는 모든 프로세스에 대해 표준 입력, 표준 출력, 표준 에러라는 세 개의 기본 파일 디스크립터를 자동으로 열어줍니다. 이를 통해 프로그램은 기본적인 입출력 작업을 바로 수행할 수 있습니다.
5. 프로그램 실행 시작
위의 모든 과정이 끝나면, 운영체제는 CPU의 제어권을 새로 생성된 프로세스에 넘겨줍니다. 이로써 프로그램은 main() 함수를 시작점으로 하여 본격적인 실행을 시작하게 됩니다.

프로세스의 메모리 구조
프로그램이 실행되면 운영체제는 프로그램이 사용할 수 있도록 메모리 공간을 여러 영역으로 나누어 할당합니다. 이러한 메모리 공간은 크게 네 가지 주요 영역으로 구성됩니다.
- 텍스트 영역: 이 영역에는 실행 가능한 프로그램의 코드가 저장됩니다. 텍스트 영역은 읽기 전용이며, 여러 프로세스가 동일한 코드를 공유할 수 있기 때문에 메모리 효율성이 높습니다.
- 데이터 영역: 전역 변수와 정적 변수가 저장되는 공간입니다. 이 영역은 다시 두 부분으로 나뉩니다.
- 초기화된 데이터(Initialized Data): 코드를 시작할 때 초기값이 명시된 전역 및 정적 변수들이 저장됩니다.
- 초기화되지 않은 데이터(Uninitialized Data): 초기값이 없는 전역 및 정적 변수들이 저장됩니다.
- 힙(Heap) 영역: 프로그래머가 필요에 따라 동적으로 메모리를 할당하고 해제할 수 있는 공간입니다. malloc()이나 new 같은 함수를 사용해 할당한 메모리가 여기에 저장됩니다. 힙은 낮은 주소에서 높은 주소로, 스택과 반대 방향으로 자라납니다.
- 스택(Stack) 영역: 함수 호출 시 생성되는 임시 데이터를 저장하는 공간입니다. 함수 내의 지역 변수, 함수 매개변수, 그리고 함수가 호출된 후 돌아올 주소 등이 여기에 저장됩니다. LIFO 구조로 작동합니다.
가장 중요한 점은 각 프로세스는 자신만의 독립적인 메모리 주소 공간을 가진다는 것입니다. 이는 한 프로세스가 다른 프로세스의 메모리를 침범하거나 영향을 주지 않도록 보호하는 역할을 합니다.
프로세스 상태
간단하게 Process는 3가지 상태를 가집니다.
- Running: CPU를 할당받아 명령어를 실제로 처리하고 있다는 의미입니다. 즉, 컴퓨터가 그 프로세스를 위해 일하고 있는 순간입니다.
- Ready: 프로세스가 CPU를 사용할 모든 준비가 끝났지만, 현재 다른 프로세스가 CPU를 사용하고 있어 대기 중인 상태입니다. 실행 상태로 전환될 수 있는 대기열에 있다고 생각하면 됩니다. 운영체제가 다음 차례에 어떤 프로세스를 실행시킬지 결정하면 이 상태의 프로세스 중 하나가 선택됩니다.
- Blocked: 특정 이벤트가 발생하기를 기다리고 있는 상태입니다. 예를 들어, 하드디스크에서 데이터를 읽어오거나(I/O 요청) 사용자의 입력을 기다리는 경우 등이 있습니다. 이 상태에서는 CPU를 사용하더라도 의미가 없으므로, 기다리는 이벤트가 완료될 때까지 CPU 할당 대상에서 제외됩니다. 이벤트가 완료되면 이 프로세스는 다시 '준비' 상태로 돌아가 CPU 할당을 기다립니다.

운영체제의 핵심 데이터 구조
운영체제는 시스템 내에서 실행되는 모든 프로세스를 효율적으로 관리하기 위해 여러 가지 데이터 구조를 사용합니다. 이 구조들은 각 프로세스의 상태와 정보를 체계적으로 추적하고 저장하는 역할을 합니다.
1. 프로세스 목록 (Process List)
운영체제는 현재 시스템에 있는 모든 프로세스들의 목록을 관리합니다. 이 목록에는 Running, Ready, Blocked 상태에 있는 모든 프로세스가 포함됩니다. 이를 통해 운영체제는 어떤 프로세스가 CPU를 사용할 차례인지, 어떤 프로세스가 특정 이벤트를 기다리고 있는지 등을 한눈에 파악할 수 있습니다.
2. 레지스터 컨텍스트 (Register Context)
레지스터 컨텍스트는 프로세스가 CPU 사용을 멈추었을 때 CPU의 레지스터에 저장되어 있던 값들을 보관하는 데이터 구조입니다. 컨텍스트 스위칭(Context Switching)이 일어날 때 필수적인 역할을 합니다.
- Save: 현재 실행 중인 프로세스가 멈추고 다른 프로세스로 전환될 때, 해당 프로세스의 레지스터 값들을 이 컨텍스트에 저장합니다.
- Restore: 멈췄던 프로세스가 다시 CPU를 할당받아 실행될 때, 저장해 두었던 레지스터 값들을 다시 CPU 레지스터에 복원하여 중단된 지점부터 이어서 실행할 수 있게 합니다.
3. 프로세스 제어 블록 (PCB, Process Control Block)
프로세스 제어 블록(PCB)은 개별 프로세스에 대한 모든 중요한 정보를 담고 있는 데이터 구조체입니다. 마치 프로세스의 신분증과 같아서, 운영체제는 PCB를 통해 해당 프로세스의 상태와 정보를 파악하고 제어합니다.
PCB에 포함되는 주요 정보는 다음과 같습니다.
- 프로세스 상태: 현재 프로세스가 실행, 준비, 대기 중 어떤 상태인지에 대한 정보
- 프로세스 ID: 프로세스를 식별하기 위한 고유 번호
- CPU 레지스터 정보: 위에서 설명한 레지스터 컨텍스트
- 메모리 관리 정보: 프로세스에 할당된 메모리 영역에 대한 정보
- 파일 관리 정보: 프로세스가 열고 있는 파일 목록 등 입출력 관련 정보
운영체제는 이 PCB를 통해 각 프로세스를 독립적으로 관리하고, 프로세스 간의 전환을 효율적으로 처리합니다.
다중 CPU 가상화 방법
운영체제(OS)는 CPU 가상화를 통해 하나의 물리적인 CPU만 있더라도 여러 개의 CPU가 존재하는 것처럼 보이게 만듭니다. 이 가상화는 'time sharing' 기술로 구현됩니다.
Time Sharing 방식
time sharing은 여러 프로세스에게 CPU 사용 시간을 아주 짧게 나누어 번갈아 할당하는 방식입니다.
- 한 프로세스 실행: 운영체제가 특정 프로세스에 CPU를 할당하여 일정 시간 동안 실행시킵니다.
- 잠시 중단: 정해진 시간이 지나면 현재 실행 중인 프로세스를 잠시 멈춥니다.
- 다른 프로세스로 전환: CPU를 다른 프로세스에 할당하여 실행시킵니다.
- 반복: 이 과정을 매우 빠르게 반복합니다.
이러한 빠른 전환 덕분에 사용자 입장에서는 모든 프로그램이 동시에 실행되는 것처럼 느껴지게 됩니다. 하지만 이러한 잦은 전환은 시스템의 성능에 영향을 줄 수 있습니다.
가상화 구현을 위한 두 가지 요소
운영체제가 CPU 가상화를 효과적으로 구현하려면 두 가지 핵심 요소가 필요합니다.
- 낮은 수준의 기술 (Low-level machinery): 메커니즘
- 무엇을 할 것인가? (How to do something?)
- 이는 실제로 프로세스 간에 CPU 제어권을 전환하는 기술을 의미합니다. 대표적으로 컨텍스트 스위칭(Context Switching)이 있습니다. 컨텍스트 스위칭은 현재 실행 중인 프로세스의 상태를 저장하고, 다음에 실행할 프로세스의 상태를 불러오는 과정을 말합니다.
- 높은 수준의 사고 (High-level intelligence): 정책
- 무엇을 해야 하는가? (What should be done?)
- 이는 여러 준비 상태의 프로세스 중에서 다음에 어떤 프로세스를 실행시킬지 결정하는 규칙을 의미합니다. 이를 스케줄링(Scheduling)이라고 합니다. 예를 들어, 어떤 프로세스에 더 높은 우선순위를 줄지, 또는 각 프로세스에 얼마나 많은 시간을 할당할지 등을 결정하는 것입니다.
결론적으로, 운영체제는 컨텍스트 스위칭이라는 기술적 메커니즘을 사용하여 스케줄링이라는 정책에 따라 CPU를 효과적으로 분할함으로써 여러 개의 CPU가 있는 것처럼 사용자에게 가상화된 환경을 제공합니다.
출처: 경북대학교 한명균 교수님, “운영체제” 강의 자료
'CS > OS' 카테고리의 다른 글
[OS] 주소 변환(Address Translation)과 Base-and-Bounds (1) 2025.10.04 [OS] 가상 메모리(Virtual Memory)의 원리와 작동 방식 (0) 2025.09.24 [OS] Priority Inversion부터 MLFQ까지: 스케줄링 문제와 해결책 (0) 2025.09.17 [OS] CPU 스케줄링의 원리와 알고리즘: FIFO, SJF, STCF, RR 비교와 I/O 통합 (0) 2025.09.15 [OS] Direct Execution과 Limited Direct Execution: CPU 가상화의 핵심 원리 (0) 2025.09.15