복숭아.
자 이제 그 복숭아를 진짜 복숭아라 하자.
이 복숭아를 먹고 싶은 사람은 많아.
우리는 그들 각각에게 복숭아를 주고 싶은 거야. 그래야 모두 행복해 할테니까.
먹고 싶은 사람들에게 주는 복숭아를 가상 복숭아라고 부르자.
어떻게든 우리는 하나의 진짜 복숭아로부터 많은 가상 복숭아를 만들어야 해.
그리고 중요한 사실 : 이 환상에서, 먹고 싶은 사람들은 진짜 복숭아를 가지고 있는 것처럼 보이지만 실제로는 그렇지 않다는 것이다
그래서 모르는 사이에 복숭아를 공유한다는 말이죠?
그게, 만일 제가 다른 사람과 복숭아를 공유한다면, 알아차릴 수 있을 것 같은데요
그러나 먹고 싶은 사람들은 눈치채지 못한다는 거지.
대부분의 시간 동안 그들은 낮잠을 자거나 다른 일을 하고 있지.
따라서 이 시간 동안 자네는 복숭아를 낚아채서 다른 사람에게 줄 수 있는 거지.
이렇게 해서 여러 개의 가상 복숭아가 있다는 환상, 사람마다 하나씩 복숭아를 가지고 있는 환상을 만들어 내는 거지.
CPU.
시스템에 딱 한 개의 CPU만 존재한다고 가정하자.
물론 현재는 둘 또는 넷 또는 그 이상의 CPU를 가진 시스템도 있지만.
가상화는 이 한 개의 CPU를 각 응용 프로그램에게 여러 개의 CPU인 것처럼 보이도록 하는 일을 하지.
그래서 각 응용 프로그램은 자신만 사용하는 CPU를 가지게 되었다고 생각하지만
실제로는 한 개의 CPU만 있는 거지.
그렇게 운영체제는 멋진 환상을 만들어 내는 거야.
CPU를 가상화 한거지
프로그램
프로그램 자체는 생명이 없는 존재다
- 디스크 상에 존재
- 실행을 위한 명령어와 정적 데이터의 묶음
이 명령어와 데이터 묶음을 읽고 실행하여 프로그램에 생명을 불어넣는 것이 운영체제이다.
사용자는 하나 이상의 프로그램을 동시에 실행시키기를 원한다.
웹 브라우저, 메일 프로그램, 게임, 음악 플레이어 등을 실행하는 데스크톱 또는 랩톱 컴퓨터를 생각해 보라.
컴퓨터들은 동시에 수십 혹은 수백 발의 프로세스를 실행하는 것처럼 보인다.
여러 프로그램을 동시에 실행할 수 있으면, 시스템을 쉽게 사용할 수 있다.
사용자는 사용 가능한 CPU가 있는지 신경쓰지 않고 그저 프로그램만 실행시키면 된다.
CPU가 여러 개 존재한다는 환상을 어떻게 제공하는가 ?
적은 개수의 CPU로 운영체제는 어떻게 거의 무한에 가까운 CPU가 있는 듯한 환상을 만들 수 있을까?
운영체제는 CPU를 가상화하여 이러한 환상을 만들어 낸다.
하나의 프로세스를 실행 하고, 얼마 후 중단시키고 다른 프로세스를 실행하는 작업을 반복하면서
소수의 CPU로 여러 개의 가상 CPU가 존재하는 듯한 환상을 만들어 낸다.
시분할(time sharing)
원하는 수 만큼의 프로세스를 동시에 실행할 수 있게 한다.
CPU를 공유하기 때문에, 각 프로세스의 성능은 낮아진다.
운영체제에서 CPU 가상화를 잘 구현하기 위해, 저수준의 도구와 고차원적인 “지능” 이 필요하다.
저수준 도구: 메커니즘(mechanism)
메커니즘은 필요한 기능을 구현하는 방법이나 규칙을 의미한다.
CPU에서 프로그램 실행을 잠시 중단하고
다른 프로그램을 실행하는 것을 문맥 교환이라고 한다.
이 시분할 기법은 모든 현대 운영체제들이 채택하고 있다
시분할(time sharing)
자원 공유를 운영체제가 사용하는 가장 기본 기법 중 하나이다.
한 개체가 잠깐 자원을 사용한 후, 다른 발체가 또 잠깐 자원을 사용하고, 그 다음 발체가 사용하면서
이 자원 (CPU 또는 네트워크 링크 등)을 많은 발체들이 공유한다.
공간 분할(space sharing)
공간 분할은 객체에게 공간을 분할해 준다.
공간 분할의 예로 디스크가 있다.
디스크는 자연스럽게 공간 분할할 수 있는 자원으로,
블럭이 하나의 파일에 할당되면 파일을 삭제하기 전에는 다른 파일이 할당될 가능성이 낮다.
스케줄링 정책(scheduling policy)
운영체제 내에서 어떤 결정을 내리기 위한 알고리즘이다.
실행 가능한 여러 프로그램들이 있을 때, 운영체제는 어느 프로그램을 실행시켜야 하는가?
스케줄링 정책은
- 과거 정보 (직전 1분 동안 어떤 프로그램이 자주 실행되었는지)
- 워크로드에 관한 지식 (어떤 유형의 프로그램들이 실행되었는지)
- 성능 측정 결과 (시스템이 대화 성능 혹은 처리량을 높이려 하는지)
프로세스(process)의 개념

실행 중인 프로그램
실행되는 동안 접근했거나 영향을 받은 자원의 목록
프로세스의 구성 요소를 이해하기 위해서 하드웨어 상태(machine state)를 이해
프로그램이 실행되는 동안 하드웨어 상태를 읽거나 갱신할 수 있다.
이때 가장 중요한 하드웨어 구성 요소는 무엇일까? 메모리
명령어는 메모리에 저장된다.
실행 프로그램이 읽고 쓰는 데이터 역시 메모리에 저장된다.
프로세스가 접근할 수 있는 메모리(주소 공간(address space)이라 불림)는 프로세스를 구성하는 요소이다.
레지스터도 프로세스의 하드웨어 상태를 구성하는 요소 중 하나이다.
많은 명령어들이 레지스터를 직접 읽거나 갱신한다.
프로세스를 실행하는 데 레지스터도 빠질 수 없다.
프로세스의 하드웨어 상태를 구성하는 레지스터 중에 특별한 레지스터들이 존재한다.
프로그램 카운터(program counter, PC)
프로그램의 어느 명령어가 실행 중인지를 알려준다.
명령어 포인터(instruction pointer, IP)
- 스택 포인터(stack pointer): 함수의 변수를 관리하는 스택 레지스터
- 프레임 포인터(frame pointer): 리턴주소를 관리하는 레지스터
프로세스 API
생성 (Create):
운영체제는 새로운 프로세스를 생성할 수 있는 방법을 제공해야 한다.
쉘에 명령어를 입력하거나, 응용 프로그램의 아이콘을 더블-클릭하여 프로그램을 실행시키면,
운영체제는 새로운 프로세스를 생성한다.
제거 (Destroy):
프로세스는 실행되고 할 일을 다하면 스스로 종료한다.
그러나 프로세스가 스스로 종료하지 않으면 사용자는 그 프로세스를 제거하길 원할 것이고,
필요없는 프로세스를 강제로 중단시키는 API는 매우 유용하다.
대기 (Wait):
때론 어떤 프로세스의 실행 중지를 기다릴 필요가 있기 때문에 여러 종류의 대기 인터페이스가 제공된다
각종 제어 (Miscellaneous Control):
프로세스의 제거, 대기 이외에, 여러 가지 제어 기능들이 제공된다.
예를 들어, 대부분의 운영체제는 프로세스를 일시정지하거나 재발 (일시정지되었던 프로세스의 실행을 다시 시작)하는 기능을 제공한다
상태 (Status):
프로세스 상태 정보를 얻어내는 인터페이스도 제공된다.
상태 정보에는 얼마 동안 실행되었는지 또는 프로세스가 어떤 상태에 있는지 등이 포함된다.
프로그램 실행을 위하여 운영체제가 하는 것
프로그램 코드와 정적 데이터 (static data, 예를 들어, 초기값을 가지는 변수) 를 메모리, 프로세스의 주소 공간에 탑재(load)하는 것이다.
프로그램은 디스크 또는 요즘 시스템에서는 플래시-기반 SSD에 특정 실행 파일 형식으로 존재한다.
코드와 정적 데이터를 메모리에 탑재하기 위해서 운영체제는 디스크의 해당 데이터를 읽어서 메모리의 어딘가에 저장해야 한다
초기 운영체제: 프로그램 실행 전에 코드와 데이터를 모두 메모리에 탑재하였다.
현대의 운영체제: 프로그램을 실행하면서 코드나 데이터가 필요할 때 필요한 부분만 메모리에 탑재한다.
어떤 프로그램이든 실행시키기 전에 운영체제는 프로그램의 중요 부분을 디스크에서 메모리로 탑재해야 한다
페이징(paging)
스와핑(swapping)
일정량의 메모리가 프로그램의 실행시간 스택(run-time stack, 혹은 그냥 스택) 용도로 할당되어야 한다.
운영체제는 스택을 주어진 인자로 초기화한다.
특히, main()함수의 인자인 argc와 argv 벡터를 사용하여 스택을 초기화한다.
운영체제는 프로그램의 힙(heap)을 위한 메모리 영역을 할당한다.
C 프로그램에서 힙(heap)은 동적으로 할당된 데이터를 저장하기 위해 사용
프로그램은 malloc()을 호출하여 필요한 공간을 요청
free()를 호출하여 사용했던 공간을 반환하여 다른 프로그램이 사용할 수 있도록 한다.
힙(heap)은 연결 리스트, 해시 테이블, 트리 등 크기가 가변적인 자료 구조를 위해 사용된다.
프로그램이 실행되면 malloc() 라이브러리 API 를 호출하여 메모리를 요청하고,
운영체제가 이를 충족하도록 메모리를 할당한다.
운영체제는 또 입출력과 관계된 초기화 작업을 수행한다.
세 개의 파일 디스크립터(File descriptor)
Unix 시스템 에서 각 프로세스는 기본적으로
- 표준 입력 (STDIN)
- 표준 출력 (STDOUT)
- 표준 에러 (STDERR)
디스크립터들을 사용하여 프로그램은
터미널로부터 입력을 읽고, 화면에 출력을 프린트 하는 작업을 쉽게 할 수 있다.
코드와 정적 데이터를 메모리에 탑재하고,
스택과 힙을 생성하고 초기화하고,
입출력 셋업과 관계된 다른 작업을 마치게 되면,
운영체제는 프로그램 실행을 위한 준비를 마치게 된다.
프로그램의 시작 지점 (entry point), 즉 main()에서부터 프로그램 실행을 시작하는 마지막 작업만이 남는다.
main() 루틴으로 분기함으로써
운영체제는 CPU를 새로 생성된 프로세스 에게 넘기게 되고 프로그램 실행이 시작된다.
프로세스 상태(state)
프로세스 상태의 발념은 초기 컴퓨터 시스템에서 등장

실행 (Running):
실행 상태에서 프로세스는 프로세서에서 실행 중이다. 즉, 프로세스는 명령어를 실행하고 있다.
준비 (Ready):
준비 상태에서 프로세스는 실행할 준비가 되어 있지만 운영체제가 다른 프로세스를 실행하고 있는 등의 이유로 대기 중이다.
대기 (Blocked):
프로세스가 다른 사건을 기다리는 동안 프로세스의 수행을 중단시키는 연산이다.
프로세스가 디스크에 대한 입출력 요청을 하였을 때
프로세스는 입출력이 완료될 때까지 대기 상태가 되고, 다른 프로세스가 실행 상태로 될 수 있다.
실행 상태 -> 준비 상태로의 전이:
프로세스가 나중에 다시 스케줄 될 수 있는 상태가 되었다는 것을 의미한다.
프로세스가 입출력 요청 등의 이유로 대기 상태가 되면
요청 완료 등의 이벤트가 발생할 때까지 대기 상태로 유지된다.
이벤트가 발생하면 프로세스는 다시 준비 상태로 전이되고
운영체제의 결정에 따라 바로 다시 실행될 수도 있다.
두 개의 프로세스가 어떻게 전이될 수 있는지를 보여주는 예를 보자.
실행 중인 두 프로세스가 있다고 하자.
각 프로세스는 오직 CPU만 사용하고 입출력을 행하지 않는다.


첫 번째 프로세스가 어느 정도 실행한 후에 입출력을 요청한다.
그 순간 프로세스는 대기 상태가 되고 다른 프로세스에게 실행 기회를 준다
Process0은 입출력을 요청하고 요청한 작업이 완료되기를 기다린다.
프로세스는 디스크를 읽거나 네트워크로부터 패킷을 기다릴 때 대기 상태로 전이한다.
운영체제는 Process0이 CPU를 사용하지 않는다는 것을 감지하고 Process1 을 실행시킨다.
Process1이 실행되는 동안 입출력은 완료되고 Process0은 준비 상태로 다시 전이된다.
결국 Process1은 종료되고 Process0이 실행되어 종료된다.
프로세스 제어 블럭(Process Control Block, PCB)
프로세스의 관리를 위한 정보를 저장하는 자료 구조를 이라 부른다. 각 프로세스에 관한 정보를 저장하는 C 자료 구조를 이야기 할 때 부르는 멋진 이름이다.
레지스터 문맥(register context) 자료 구조
프로세스가 중단되ᨩ을 때 해당 프로세스의 레지스터값들을 저장한다.
이 레지스터값들을 복원하여 (예, 해당 값을 실제 물리 레지스터에 다시 저장함으로써)
운영체제는 프로세스 실행을 재개(문맥 교환context switch)한다.

그림에서 실행, 준비, 대기 외에 다른 상태들이 존재하는 것을 볼 수 있다.
초기(initial) 상태를 가지는 시스템도 있다.
프로세스가 생성되는 동안에는 초기 상태 에 머무른다.
프로세스는 종료되었지만 메모리에 남아있는 상태인 최종(inal)상태도 있다
(Unix-기반 시스템에서 이 상태는 좀비(zombie)상태라고 부른다)
프로세스가 성공적으로 실행했는지를 다른 프로세스 (보통은 부모(parent)프로세스) 가 검사하는 데 유용하다.
-> 최종 상태를 활용
- 프로세스가 성공적으로 종료되었으면 0 반환
- 그렇지 않으면 0이 아닌 값을 반환
부모 프로세스는 자식 프로세스의 종료를 대기하는 시스템 콜을 호출 == wait()
이 호출은 종료된 프로세스와 관련된 자원들을 정리할 수 있다고 운영체제에 알리는 역할도 한다.
'학습 기록 (Learning Logs) > Today I Learned' 카테고리의 다른 글
머신러닝 (0) | 2025.03.21 |
---|---|
✨ Operating Systems: Three Easy Pieces ✨ - 프로세스 (0) | 2025.03.19 |
빅데이터 (0) | 2025.03.18 |
Spring Boot + STOMP로 카카오톡 스타일 채팅방 만들기 (0) | 2025.03.10 |
인공 지능을 실현하기 위한 기술 (0) | 2025.03.09 |