빙응의 공부 블로그
[OSTEP 가상화(virtualization)]Chapter 4 프로세스의 개념 본문

이 장에서는 운영체제가 제공하는 핵심 개념 중 하나인 프로세스(process)에 대해 논의합니다.
운영체제란?
일반적으로 프로세스는 실행 중인 프로그램으로 정의합니다.
프로그램 자체는 생명이 없는 존재이며 프로그램은 디스크 상에 존재하는 실행을 위한 명령어와 정적 데이터의 묶음입니다.
이 명령어와 데이터 묶음을 읽고 실행하여 프로그램에 생명을 불어넣는 것이 바로 운영체제입니다.
사용자는 하나 이상의 프로그램을 동시에 실행하기 원합니다. 우리가 컴퓨터를 사용할때 컴퓨터들이 동시에 수십 혹은 수백 개의 프로세스를 실행하는 것처럼 보입니다. 사용자는 사용 가능한 CPU를 신성쓰지 앟고 그저 프로그램만을 실행한다.
이때 우리의 도전과제는 다음과 같습니다.
적은 CPU로 여러 개가 존재한다는 환상을 어떻게 제공하는가?
운영체제는 CPU를 가상화하여 이러한 환상을 만들어냅니다. 나의 프로세스를 실행하고, 얼마 후 중단시키고 다른 프로세스를 빠르게 실행시키는 것으로 여러 개의 가상 CPU가 존재하듯이 만들어냅니다.
시분할(timesharing)이라 불리는 기법은 원하는 수 만큼의 프로세스를 동시에 실행할 수 있게 합니다.
쉽게 설명하면 CPU가 현재 실행 중인 프로세스의 상태를 저장하고, 다른 프로세스를 실행하기 위해 해당 프로세스의 상태를 복원하는 과정을 반복하는 것을 말합니다. 시분할 기법은 CPU를 공유하기에 각 프로세스의 성능은 낮아집니다.
운영체제에서 CPU 가상화를 잘 구현하기 위해, 저수준의 도구와 고차원적인 "지능"이 필요합니다.
저수준 도구를 메커니즘이라고 합니다. 메커니즘은 필요한 기능을 구현하는 방법이나 규칙을 의미합니다.
예로 문맥 교환(컨텍스트 스위칭)은 시분할의 핵심이며 프로그램을 잠시 중단하고 다른 프로그램을 실행하는 것입니다. 이러한 것을 메커니즘이라고 합니다.
운영체제의 지능은 정책의 형태로 표현됩니다. 정책은 운영체제 내에서 어떤 결정을 내리기 위한 알고리즘입니다.
운영체제의 스케줄링 정책도 이러한 결정을 내리며 이러한 결정을 내리기 위해 과거의 정보, 워크로드에 관한 지식, 성능 측정 결과를 이용합니다.
📝7.1 프로세스의 개념
운영체제는 실행 중인 프로그램의 개념을 제공합니다. 이를 프로세스라고 합니다.
프로세스의 구성 요소를 이해하기 위해서는 하드웨어 상태를 이해해야합니다. 프로그램이 실행되는 동안 하드웨어 상태를 읽거나 갱신할 수 있습니다. 이때 가장 중요한 하드웨어 구성 요소는 메모리입니다. 명령어는 메모리에 저장되며 실행 프로그램이 읽고 쓰는 데이터 역시 메모리에 저장됩니다. 프로세스가 접근할 수 잇는 메모리(주소 공간)는 프로세스를 구성하는 요소입니다.
레지스터도 프로세스의 하드웨어 상태를 구성하는 요소 중 하나입니다. 많은 명령어들이 레지스터를 직접 읽거나 갱신합니다. 그래서 프로세스를 실행하는 데 레지스터도 빠질 수 없습니다.
프로세스의 하드웨어 상태를 구성하는 레지스터 중에 특별한 레지스터들이 존재합니다.
- 프로그램 카운터(PC)는 프로그램의 어느 명령어가 실행 중인지 알려줍니다.
- 스택 포인터와 프레임 포인터는 함수의 변수와 리턴 주소를 저장하는 스택을 관리할 때 사용하는 레지스터입니다.
또한 프로그램은 영구 저장자치에 접근하기도 합니다.
정책과 구현의 분리
많은 운영체제에서 공통된 설계 패러다임은 고수준 정책을 저수준 기법으로부터 분리하는 것입니다.
기법은 시스템에 관한 "어떻게?"라는 질문에 답을 제공합니다. 예를 들어, "운영체제는 어떻게 문맥 교환을 구현하는가?" 등이 해당됩니다.
정책은 "어느 것?"이라는 질문에 답합니다. 예를 들어, "운영체제는 지금 어느 프로세스를 실행시켜야 하는가?"를 결정하는 기준입니다.
이 둘의 차이점은 기법이 방법에 초점을 맞춘다면, 정책은 판별 기준에 초점을 둡니다.
둘의 분리는 정책을 변경할 때 기법의 변경을 고민하지 않도록 설계하는 데 그 목적이 있습니다. 이는 일반적인 소프트웨어 설계 원칙인 모듈성의 한 형태입니다.
내 생각
기법이 더 큰 의미로 보일 수도 있습니다.
즉, 기법 안에 정책이 포함된 것처럼 보이는 이유는 기법이 정책을 실행하는 기반을 제공하기 때문입니다.
하지만 그렇지 않습니다.
기법은 구체적인 실행 방식을 의미하며, "문맥 교환을 어떻게 구현할 것인가?"와 같은 구체적이고 기술적인 문제를 다룹니다.
반면, 정책은 기법 위에서 동작하며, 기법을 활용해 의사 결정을 내립니다.
즉, 정책은 "어떤 프로세스를 실행할 것인가?"와 같은 추상적인 기준을 정의합니다.
따라서 기법이 없으면 정책을 실행할 수 없고, 정책이 없으면 기법의 방향성이 없습니다.
결국, 기법과 정책은 서로 상호보완적인 관계를 가지며, 어느 하나가 다른 하나를 포함하거나 더 큰 의미를 가진다고 보기는 어렵습니다.
📝7.2 프로세스 API
실제 프로세스 API에 대한 논의는 다음 장에 다루겠지만 운영체제는 반드시 API로 제공해야 하는 몇몇 기본 기능을 알아봅시다.
- 생성(Create) : 운영체제는 새로운 프로세스를 생성할 수 잇는 방법을 제공합니다.
- 제거(Destroy) : 프로세스 생성 인터페이스를 제공하는 것처럼 강제로 제거할 수 잇는 인터페이스를 제공합니다.
- 대기(Wait) : 때론 어떤 프로세스의 실행 중지를 기다릴 필요가 있기에 대기가 제공됩니다.
- 각종 제어
- 상태 : 프로세스 상태 정보를 얻어내는 인터페이스도 제공됩니다.
📝7.3 프로세스 생성 : 좀 더 자세하게
우리가 밝혀내야 할 한 가지 미스터리는 "프로그램이 어떻게 프로세스로 변형되는가?"입니다.
운영체제는 어떻게 프로그램을 준비하고 실행시키는가?
실제로 어떻게 프로세스를 생성하는가?

프로그램 실행을 위하여 운영체제가 하는 첫 번째 작업은 프로그램 코드와 정적 데이터(초기값)를 메모리, 프로세스 주소 공간에 탑재하는 것입니다. 프로그램은 디스크 또는 요즘 시스템에서는 플래시-기반 SSD에 특정 실행 파일 형식으로 존재합니다. 운영체제는 메모리 탑재를 위해 디스크의 해당 바이트를 읽어서 저장해야합니다.
초기 운영체제들은 프로그램 실행 전에 코드와 데이터를 모두 메모리에 탑재했지만 현대의 운영체제들은 필요할 때 메모리에 탑재합니다. 코드의 데이터의 늦은 탑재의 동작을 정확히 이해하기 위해서는 페이징과 스와핑 동작의 이해가 필요합니다. 나중에 메모리 가상화에 대해 다룰 때 자세히 알게될 것입니다.
지금은 어떤 프로그램이든 실행시키기 전에 운영체제는 프로그램의 중요 부분을 디스크에서 메모리로 탑재해야한다는 것만 알면된다.
코드와 정적 데이터가 메모리에 탑재된 후 프로세스를 실행시키기 전에 운영체제가 할일이 몇개 있습니다.
일정량의 메모리가 프로그램의 실행시간 스택 용도(프로그램이 실행될 때, 임시 데이터 관리)로 할당되어야 합니다.
C프로그램은 지역 변수, 함수 인자, 리턴 주소 등을 저장하기 위해 스택을 사용합니다. 운영체제는 스택을 주어진 인자로 초기화합니다. 특히, main() 함수의 인자인 argc와 argv 벡터를 사용하여 스택을 초기화합니다.
운영체제는 프로그램의 힙(heap)을 위한 메모리 영역을 할당합니다. C 프로그램에서 힙은 동적으로 할당된 데이터를 저장하기 위해 사용됩니다. 프로그램은 malloc()을 호출하여 필요한 공간을 요청하고 free()를 호출하여 사용한 공간을 반환합니다.
또한 힙은 연결 리스트, 해시 테이블, 트리 등 크기가 가변적인 자료 구조를 위해 사용됩니다.
운영체제는 또 입출력과 관계된 초기화 작업을 수행합니다. 예를 들어 UNIX 시스템는 표준 입력, 표준 출력, 표준 에러 장치에 해당하는 세 개의 파일 디스크립터를 갖는데, 이 디스크립터를 사용하여 프로그램은 터미널로부터 입력을 읽고 화면에 출력을 프린트합니다.
- 코드와 정적 데이터를 메모리에 탑재
- 스택과 힙을 생성하고 초기화
- 입출력 셋업 관련 작업
이 세가지 작업을 마치면 프로그램의 시작지점, 즉 main()에서부터 프로그램 실행을 시작하는 마지막 작업만이 남습니다. main 루틴으로 분기함으로써 운영체제는 CPU를 새로 생성된 프로세스에게 넘기게되고 프로그램 실행이 시작됩니다.
📝7.4 프로세스 상태
프로세스가 무엇인지 알아보았으니 이제 프로세스의 상태에 대해 논의해봅시다.
프로세스 상태의 개념은 초기 컴퓨터 시스템에서 등장하였습니다. 단순화하면 세 상태입니다.
- 실행(Running) : 실행 상태에서 프로세스는 포로세서에서 실행중이다.
- 준비(Ready) : 준비 상태에서 프로세스는 실행 준비는 되었지만 운영체제가 다른 프로세스를 실행하고 있어 대기중이다.
- 대기(Blocked) " 프로세스가 다른 사건을 기다리는 동안 프로세스 수행을 중단하는 연산이다.
이러한 상태를 그림으로 표현하면 아래와 같습니다.
프로세스는 준비 상태와 실행 상태를 운영체제의 정책에 따라 이동합니다. 프로세스는 운영체제의 스케줄링 정책에 따라 스케줄되면 준비상태에서 실행 상태로 전이합니다.

실행 상태에서 준비 상태로의 전이는 프로세스가 나중에 다시 스케줄 될 수 있는 상태입니다.
프로세스가 입출력 요청 등의 이유로 대기 상태가 되면 요청 완료 등의 이벤트가 발생할 때까지 대기 상태가 됩니다. 이벤트가 발생하면 프로세스는 다시 준비 상태로 전이되고 운영체제의 결정에 따라 바로 실행될 수 있습니다.

해당 과정의 모든 순서는 운영체제의 스케줄러가 관리합니다.
여담 : 자료구조- 프로세스 리스트
운영체제는 다양한 중요 자료 구조들이 존재합니다. 프로세스 리스트는 시스템에서 실행 중인 프로그램을 관리합니다. 프로세스의 관리를 위한 정보를 저장하는 자료 구조를 프로세스 제어 블럭(PCB)라 부릅니다.
📝7.5 자료 구조
운영체제도 일종의 프로그램입니다. 다른 프로그램들과 같이 다양한 정보를 유지하기 위한 자료구조를 가집니다.
예를 들어 프로세스 상태를 파악하기 위해 준비 상태의 프로세스들을 위한 프로세스 리스트와 같은 자료구조를 유지합니다.
또한 어느 프로세스가 실행 중인지 파악을 위한 부가적인 자료구조도 포함됩니다. 운영체제는 실행, 준비, 대기 상태의 프로세스를 파악하기 위한 자료 구조를 가지고 있습니다.
아래 그림은 프로세스 추적을 위한 정보가 보입니다. 모든 운영체제는 비슷한 프로세스 구조를 갖고 있으며 물론 훨씬 복잡합니다.
그림을 통해서 운영체제가 관리하는 프로세스 정보를 알 수 있습니다.
레지스터 문맥 자료 구조는 프로세스가 중단되었을 때 해당 프로세스의 레지스터 값을 저장합니다. 나중에 다시 실행할 때 이 레지스터값을 복원하여 재실행합니다. 이를 문맥 교환이라고 합니다.

위 그림을 보면 다양한 상태를 볼 수 있는데, 초기 상태를 가지는 시스템도 있다. 프로세스가 생성되는 동안에는 초기 상태에 머무르며 프로그램 종료되었지만 메모리에 남아있는 상태인 최종 상태도 있다. 이 상태에서 프로세스가 성공적으로 실행했는지를 다른 프로세스가 검사하는 데 유용하며 이를 위해 최종 상태를 확인한다.(리눅스 기준 이 상태에서 부모 프로세스는 종료되었으나 자식 프로세스가 최종으로 남아있는 것을 좀비 상태로 불린다)
프로세스는 자식 프로세스의 종료를 대기하는 시스템 콜을 호출한다. 이 호출은 종료된 프로세스와 관련된 자원을 정리하고 운영체제에 알린다.
📝7.6 요약
1. 프로세스란 무엇인가?
- 프로세스 정의: 실행 중인 프로그램.
- 프로그램과의 차이: 프로그램은 단순히 디스크 상에 저장된 명령어와 데이터이며, 운영체제가 이를 실행시켜 프로세스로 변환.
- CPU 가상화: 시분할(timesharing) 기법으로 한 CPU가 여러 프로세스를 동시에 실행하는 것처럼 보이게 함.
2. 프로세스의 구성 요소
- 주소 공간: 프로세스가 접근 가능한 메모리.
- 레지스터:
- 프로그램 카운터(PC): 실행 중인 명령어 위치.
- 스택 포인터 및 프레임 포인터: 함수 호출 시 변수 및 리턴 주소 관리.
- 힙(Heap): 동적 메모리 할당용.
- 스택(Stack): 함수 호출 및 지역 변수 저장.
3. 프로세스 생성 과정
- 코드 및 데이터 탑재: 실행 파일을 메모리에 로드.
- 스택 생성 및 초기화: main() 함수 호출 시 인자 전달.
- 힙 할당: 동적 데이터 저장용 메모리 초기화.
- 입출력 초기화: 표준 입력/출력 설정.
'CS > 운영체제' 카테고리의 다른 글
| [OSTEP 가상화(virtualization)]Chapter 9 비례 배분 (0) | 2025.01.09 |
|---|---|
| [OSTEP 가상화(virtualization)]Chapter 8 멀티 레벨 피드백 큐 (0) | 2025.01.09 |
| [OSTEP 가상화(virtualization)]Chapter 7 CPU 스케줄링 (0) | 2025.01.07 |
| [OSTEP 가상화(virtualization)]Chapter 6 프로세스 실행 (1) | 2025.01.05 |
| [OSTEP 가상화(virtualization)]Chapter 5 프로세스 API (0) | 2025.01.05 |