기록공간

2-6장. 주소 공간의 개념 본문

OS

2-6장. 주소 공간의 개념

입코딩 2020. 3. 2. 16:51
반응형

초기에는 컴퓨터 시스템을 구현하는 것이 쉬웠다. 사용자가 많은 것을 기대하지 않았기 때문이다. 하지만 시대가 변화하면서 사용자들은 점점 편의성, 고성능, 신뢰성을 추구하게 되었다. 

 

초기 시스템

메모리 관점에서 초기 컴퓨터는 많은 개념을 사용자에게 제공하지 않았다. 컴퓨터의 물리 메모리는 다음과 같이 생겼다.

 

운영체제는 메모리에(그림에서는 물리주소 0부터) 상주하는 루틴(라이브러리)의 집합이였다. 물리 메모리에 하나의 실행 중인 프로그램(프로세스)이 존재하였고(그림에서는 물리 주소 64KB부터 시작하여) 나머지 메모리를 사용하였다. 특별한 가상화는 거의 존재하지 않았고 사용자는 운영체제로부터 그리 많은 것을 기대하지 않았다.

 

멀티프로그래밍과 시분할

시간이 흐른 후, 컴퓨터는 고가 장비였기 때문에, 사람들이 더 효과적으로 컴퓨터를 공유하기 시작했다. 멀티프로그래밍(Multi-programming) 시대가 도래하였다. 여러 프로세스가 실행 준비 상태에 있고 운영체제는 그들을 전환하면서 실행하였다.

 

예를 들어 한 프로세스가 입출력을 실행하면, CPU는 다른 프로세스로 전환하였다. 이런 전환은 CPU의 이용률을 증가시켰다. 당시에는 특히 이러한 효율성의 개선이 중요하였다. 시스템의 가격이 수십만 또는 수백만 달러나 하였기 때문이다.

 

곧 사람들이 컴퓨터를 더 많이 사용하길 원하기 시작했으며 시분할(Time-sharing)시대가 시작되었다. 많은 사람들이 일괄처리방식(Batch computing) 컴퓨팅의 한계를 인식하였다. 특히 오랜 시간이 걸리는 비효과적인 프로그램-디버그 사이클에 지친 프로그래머들이 일괄처리방식 컴퓨팅의 한계를 느꼈다. 많은 사용자가 동시에 컴퓨터를 사용하고, 현재 실행 중인 작업으로부터 즉시 응답을 원하기 때문에 대화식 이용(Interactivity)의 개념이 중요하게 되었다.

 

시분할을 구현하는 한 가지 방법은 하나의 프로세스를 짧은 시간 동안 실행시키는 것이다. 해당 기간 동안 프로세스에게 모든 메모리를 접근할 권한이 주어진다.(위 그림처럼) 그런 후에, 이 프로세스를 중단하고, 중단 시점의 모든 상태를 디스크 종류의 장치(모든 물리 메모리를 포함하여)에 저장하고 다른 프로세스의 상태를 탑재하여 또 짧은 시간 동안 실행시킨다. 시분할 시스템을 이런 식으로 엉성하게 구현하였다.

 

이런 방법에는 커다란 문제가 있다. 너무 느리게 동작한다는 것이고, 특히 메모리가 커질수록 느리게 된다. 레지스터 상태를 저장하고 복원하는 것은 빠르지만 메모리의 내용 전체를 디스크에 저장하는 것은 엄청나게 느리다. 그래서 할 일은 프로세스 전환시 프로세스를 메모리에 그대로 유지하면서, 운영체제가 시분할 시스템을 효율적으로 구현할 수 있게 하는 것이다.

 

위 그림에서는 세 개의 프로세스 A, B, C가 있고 각 프로세스는 512KB 물리 메모리에서 각기 작은 부분을 할당받았다. 하나의 CPU를 가정할 때, 운영체제는 실행할 한 개의 프로세스를 선택하고, 다른 프로세스들은 준비 큐에서 실행을 기다린다. 

 

시분할 시스템이 대중화되면서 운영체제에게 새로운 요구 사항이 부과되었다. 여러 프로그램이 메모리에 동시에 존재하려면 보호(Protection)가 중요한 문제가 된다. 한 프로세스가 다른 프로세스의 메모리를 읽거나 혹은 더 안 좋게 쓸 수 있는 상황을 원하지 않는다.

 

주소 공간

위와 같은 위험에 대비하여 운영체제는 사용하기 쉬운(Easy to use) 메모리 개념을 만들어야 한다. 이 개념이 바로 주소 공간(Address space)이다. 실행 중인 프로그램이 가정하는 메모리의 모습이다. 운영체제의 메모리 개념을 이해하는 것이 메모리를 어떻게 가상화할지를 이해하는 핵심이다.

 

주소 공간은 실행 프로그램의 모든 메모리 상태를 갖고 있다. 예를 들어, 프로그램의 코드(Code)는 반드시 메모리에 존재해야 하고 따라서 주소 공간에 존재한다. 스택은 함수 호출 체인 상의 현재 위치, 지역 변수, 함수 인자와 반환 값 등을 저장하는데 사용된다. 마지막으로 힙(Heap)은 동적으로 할당되는 메모리를 위해 사용된다. C언어에서 malloc()이나 C++, Java 객체지향언에서 new를 통해 메모리를 동적으로 할당받는다. 주소 공간 구성 요소에는 정적으로 초기화된 변수 등의 다른 것들도 있지만, 현재로선 코드, 스택 및 힙 세 가지만 있다고 가정하자.

 

위 그림은 아주 작은 주소 공간을 보이고 있다. 프로그램 코드는 주소 공간의 맨 위쪽에 위치한다. 위 그림에서는 0부터 시작해 1KB를 차지한다. 코드는 정적이기 때문에 메모리에 저장하기 쉽다. 따라서 주소 공간의 상단에 배치하고, 프로그램이 실행되면서 추가 메모리를 필요로 하지 않는다.

 

다음으로 프로그램 실행과 더불어 확장되거나 축소될 수 있는 두 종류의 주소 공간이 존재한다. 주소 공간의 상단에 존재하는 과 하단에 존재하는 스택이다. 두 메모리 영역은 확장할 수 있어야 하기 때문에 이런 방식으로 배치하고, 주소 공간의 양 끝단에 배치해야 두 영역 모두 확장하는 것이 가능하다. 두 영역은 확장 방향이 반대 방향일 수 밖에 없다. 힙은 1KB부터 시작하고 아래 방향으로 확장한다.(malloc()이나 new를 사용하였을때) 스택은 16KB에서 시작하고 위쪽 방향으로 확장한다.(사용자가 프로시저, 메서드를 호출할때)

 

그러나 스택과 힙의 이러한 배치는 관례일 뿐이다. 원한다면 주소 공간을 다른 방식으로 배치할 수 있다. 주소 공간에 여러 스레드가 공존할 때는 이런 식으로 주소 공간을 나누게 되면 동작하지 않는다.

 

주소 공간을 설명할 때, 운영체제가 실행 중인 프로그램에게 제공하는 개념(Abstraction)을 설명한다. 실제로 프로그램이 물리 주소 0에서 16KB 사이에 존재하는 것은 아니다. 실제로는 임의의 물리 주소에 탑재된다.

 

운영 체제는 물리 메모리를 공유하는 다수의 프로세스에게 프로세스 전용의 커다란 주소 공간이라는 개념을 제공해준다. 이것은 운영체제가 메모리를 가상화(Virtualizing memory) 한다고 말한다. 실행중인 프로그램은 자신이 특정 주소의 메모리에 탑재되고 매우 큰 주소 공간을 가지고 있다고 생각한다. 하지만 현실은 다르다.

 

예를 들어, 위 그림의 프로세스 A가 주소 0으로 부터(이 주소는 가상 주소이다) load 연산을 수행할 때, 운영체제는 하드웨어의 지원을 통해 물리 주소 0이 아니라 물리 주소 320KB(A가 탑재된 메모리)를 읽도록 보장한다. 이것이 메모리 가상화의 열쇠이다.

 

목표

이제 메모리 가상화라는 운영체제 기능을 논의할 시점이 되었다. 운영체제는 메모리를 가상화할 뿐 아니라 그 가상화를 멋진 방식으로 한다. 운영체제가 가상화를 멋지게 하기 위해서는, 몇 가지 목표가 필요하다.

 

가상 메모리 시스템(VM)의 주요 목표 중 하나는 투명성(Transparency)이다.(여기서의 투명성은 숨김 없이 밝혀야 한다는 것이 아닌 보여지지 않는다는 뜻이다) 운영체제는 실행중인 프로그램이 가상 메모리의 존재를 인지하지 못하도록 가상 메모리 시스템을 구현해야 한다. 프로그램은 메모리가 가상화되었다는 사실을 인지해서는 안된다. 오히려 프로그램은 자신이 전용 물리 메모리를 소유한 것처럼 행동해야 한다. 많은 작업들이 메모리를 공유할 수 있도록, 운영체제제와 하드웨어가 모든 작업을 수행한다.

 

VM의 또 다른 목표는 효율성(Efficiency)이다. 운영체제는 가상화가 시간과 공간 측면에서 효율적이도록 해야 한다. 시간적으로는 프로그램이 너무 느리게 실행되서는 안되고 공간적으로는 가상화를 지원하기 위한 구조를 위해 너무 많은 메모리를 사용해서는 안 된다. 시간-효율적인 가상화를 구현할 때, 운영체제는 TLB 등의 하드웨어 기능을 포함하여 하드웨어의 지원을 받아야 한다. (TLB는 추후에 등장)

 

마지막으로 VM의 세 번째 목표는 보호(Protection)이다. 운영체제는 프로세스를 다른 프로세스로부터 보호해야 하고 운영체제 자신도 프로세스로부터 보호해야 한다. 프로세스가 탑재, 저장, 혹은 명령어 반입 등을 실행할 때 어떤 방법으로든 다른 프로세스나 운영체제의 메모리 내용에 접근하거나 영향을 줄 수 있어서는 안 된다. 즉, 자신의 주소 공간 밖의 어느 것도 접근할 수 있어서는 안 된다. 보호 성질을 이용하여 프로세스들을 서로 고립(Isolate) 시킬 수 있다. 각 프로세스는 잘못된 혹은 악성 프로세스로부터 안전한 자신만의 공간 안에서만 실행되어야 한다.

 

앞으로 이러한 목표들을 기반으로 운영체제와 하드웨어 지원을 포함하여 메모리를 가상화하기 위해 필요한 기본적인 기법들을 살펴볼것이다.

반응형

'OS' 카테고리의 다른 글

2-8장. 주소 변환의 원리  (0) 2020.03.09
2-7장. 메모리 관리 API  (0) 2020.03.04
2-5장. 멀티프로세서 스케줄링  (2) 2020.02.28
2-4장. 스케줄링 : 멀티 레벨 피드백 큐(MLFQ)  (2) 2020.02.25
2-3장. 스케줄링 : 개요  (0) 2020.02.21
Comments