[운영체제(OS)] 메모리관리 - 주소바인딩, Contiguous allocation 그리고 MMU 란?

resilient

·

2022. 1. 22. 22:32

728x90
반응형

지난 시간까지 살펴봤던 멀티프로그래밍에서는 다른 프로세스/쓰레드 끼리 통신을 하게 되고 공유자원을 사용하다 보니 문제점도 많았고 그에 대한 해결책을 살펴봤었습니다.

이번 시간부터는 메모리에 대해서 하나하나씩 정리를 해보려고 합니다.

0. 메모리란?

 

먼저 메모리 관리란 물리적 주소(Physical Address)를 갖는 메모리 공간에서 여러 개의 프로세스를 어떻게 같이 돌릴 것인가에 대한 관리입니다. 그렇다면 물리적 주소란 무엇일까요? 한마디로 메모리 공간에서의 위치이죠.

 

우리는 '메모리를 엄청 잡아먹네, 메모리 몇이야?'라는 말을 많이 들어봤을 겁니다. 익히 들어 알고 있는 RAM이란 용어도 메모리에 관한 것이죠. 추상적으로 '프로그램을 실행시키면 실행에 필요한 데이터들이 메모리에 올라가면서 실행되는 것이구나'라고 생각할 수 있습니다.

 

프로그램의 실행은 곧 프로세스의 컨텍스트(Context)가 메모리에 올려지고, CPU에 의해 실행되는 것을 의미합니다.

 

1. 주소 바인딩(Address Binding) 이란?

 

CPU가 프로세스의 작업을 실행하기 위해서는 논리적 주소만으로는 실제 메모리의 주소를 알 수 없기 때문에 논리 주소와 위에서 언급했던 물리적 주소를 매핑해주는 작업이 필요한데 이 작업을 주소 바인딩이라고 합니다.

 

여기서 잠깐, 논리적 주소는 뭘까요?

 

아래 컴파일 타임 바인딩 방식을 읽어보면 느낌이 오시겠지만, 물리적 주소로 직접 매핑하는 방식은 사용할 수 없으니 다른 방법을 사용해야 합니다. 여기서 논리적 주소 (Logical Address)의 개념이 나오게 되죠.

 

CPU에 의해서 가상으로 생성되는 주소체계를 논리적 주소라고 합니다. 이 논리적 주소를 물리적 주소와 매핑해서 사용하게 되죠. 여기서 논리적 주소와 물리적 주소를 매핑해주는 장치가 바로 아래에서 공부해볼 MMU(메모리 관리 장치)인 것이고요!

 

자, 자세한 내용은 아래에서 살펴보도록 하죠.

 

다시 돌아와서, 주소 바인딩 방식은 아래와 같이 세 가지가 있습니다.

  • 컴파일 타임 바인딩
  • 로드 타임 바인딩
  • 실행 시간(런타임) 바인딩 

위 세 가지 주소 바인딩의 차이는 물리적 주소가 언제 결정되느냐의 차이입니다.

1-1. 컴파일 타임 바인딩(Compile Time Binding)

 

컴파일 타임 바인딩은 말 그대로 컴파일할 때 물리적 메모리 주소가 결정되는 주소 바인딩 방식입니다. 컴파일 과정은 컴파일 또는 어셈블러로 목적 코드를 만드는 과정이라고 전에 언급했었습니다. 컴파일 타임이라는 단어가 어렵게 느껴진다면 쉽게 말해서 프로그램 내부에서 사용하는 주소와 즉, 논리적 주소와 물리적 주소가 똑같다고 생각하면 됩니다.

 

그럼 현재 많이 사용하는 방식일까요? 당연히 아닙니다. 이유는 현재 우리가 쓰는 컴퓨터는 한 가지 프로세스만 실행시키지 않기 때문이죠. 현재 컴퓨터 상황도 모르고 물리적 주소를 사용하면 다른 프로세스가 실행되면서 차지하고 있는 메모리에 덮어 씌울 수도 없는 노릇이죠.

 

정리해보면 일단 여기부터 여기까지 메모리에 이 프로세스 올릴게!라고 하는 방식인데... 불가능합니다.

 

1-2. 로드 타임 바인딩(Load Time Binding)

 

로드 타임 바인딩은 프로세스의 실행이 시작될 때 물리적 주소가 결정됩니다. 

 

위에서 잠깐 설명했었던 논리적 주소를 사용하는데요, 프로세스 내부의 메모리 시작을 0번지부터 해서 상대 주소(논리적 주소)라고도 합니다. 프로세스 안에서 사용하는 메모리 주소를 프로세스 전체를 로딩할 때 이 프로세스가 로딩되는 위치에 따라서 물리적 주소를 매핑해주는 것이죠.

 

그렇다면 로드 타임 바인딩은 어떤 문제가 있을까요?

 

프로세스가 실행될 때마다 물리적 주소를 매핑해주는데, 바꿀 때마다 매핑을 새로 해주면 메모리를 로딩할 때 시간이 오래 걸리는 문제가 발생합니다. 프로그램을 실행할 때 코드 명령어를 저장하는 세그먼트(code segment)가 굉장히 많은데, 하나하나 실행할 때마다 계산을 해줘야 하기 때문이죠.

 

위 두 가지 바인딩 방식의 단점을 보완하기 위해 나온 방식이 다음에 설명할 실행 시간(런타임) 바인딩입니다.

 

1-3. 실행 시간(런타임) 바인딩

 

실행 시간 바인딩이란 말 그대로 프로그램이 실행한 후에도 물리적 주소가 변경될 수 있는 바인딩 방식입니다.

 

실행 시간 바인딩에서는 CPU가 주소를 참조할 때마다 해당 데이터가 물리적 주소의 어느 위치에 있는지 주소 매핑 테이블을 이용해서 바인딩을 확인합니다. 또한 위의 로드 타임 바인딩에서 설명했었듯이 세그먼트가 굉장히 많고 하나하나 실행할 때마다 계산을 해줄 경우 software가 아닌 hardware가 작업을 수행해주는데, 이 hardware가 바로 아래에서 설명할 MMU입니다.

 

2. 연속 메모리 할당(Contiguous allocation) 이란?

 

MMU를 알아보기 전에 메모리 구성과 분할방법에 대해서 간단하게 짚고 넘어가겠습니다.

 

메인 메모리는 운영체제뿐 아니라 여러 프로세스를 실행시킬 수 있어야 한다고 했습니다. 메모리는 일반적으로 두 개로 나누어지는데, 하나는 메모리에 올라가 있는 운영체제를 위한 것이고, 다른 하나는 사용자 프로세스를 위한 것입니다. 때문에 컴퓨터를 잘 사용하려면 가장 효율적인 방법으로 메인 메모리를 분할하고 할당해줘야 하는데요.

 

오늘은 그 방식들 중 요즘에는 쓰지 않는 연속 메모리 할당방식에 대해서 알아보겠습니다.

 

운영체제는 메모리 양 끝에 위치할 수 있지만 보통은 낮은 메모리에 위치하죠. 그 이유로는 인터럽트 벡터가 있습니다. (운영체제에서 인터럽트는 정말 빠지지 않는 개념이죠?)

 

인터럽트 벡터는 대부분 낮은 메모리에 위치하기 때문에 운영체제는 하위 메모리에 위치시키는 것이 보통이고 때문에 운영체제는 하위 메모리에 위치해있다고 가정하고 설명을 이어가 보겠습니다.

 

보통 여러 프로세스가 동시에 메모리에 적재되어 있는 것이 효율적이기 때문에 우리는 입력 큐에서 대기 중인 프로세스들에게 메모리를 어떻게 효율적으로 할당해야 하는가? 에 대한 고민을 계속해야 합니다. 위와 같은  연속 메모리 할당 시스템에서 프로세스는 연속된 메모리 공간을 차지하게 되죠. 

 

정리해보자면 연속 메모리 할당 이란 '논리적 주소가 연속적이면 물리적 주소도 연속적으로 할당된다'라는 것입니다.

 

그렇다면 왜 요즘에는 연속 메모리 할당을 쓰지 않을까요?

 

이유는 Fragmentation에 관한 건데 Paging기법이 나온 이유이기도 하죠. 다음 포스팅에서 알아보도록 하겠습니다!

 

 

3. MMU란?

 

위에서 언급했듯이, 프로세스의 논리적 주소는 실행 시점에 어떠한 하드웨어에 의해 물리적인 주소 공간으로 매핑되는데요.

 

이때, Relocation Register와 Limit Register라는 하드웨어가 논리적 주소와 물리적 주소 매핑에 사용되며, MMU register는  CPU 코어 안에 탑재되어 이 두 가지 레지스터의 값을 더하여 논리적 주소로부터 물리적 주소 공간을 지정해주는 레지스터를 말합니다

 

 

MMU 방식에서는 기준 레지스터 값 + 논리적 주소 값을 통해서 주소 바인딩을 합니다.


만약 해당 값이 해당 프로세스의 주소 범위를 넘어가는 값이 된다면 어떻게 될까요? 프로세스가 접근해서는 안 되는 영역을 접근할 가능성이 생기겠죠? 이런 문제점을 방지하기 위해서 memory Protection을 적용한 한계 레지스터를 사용하는 것입니다.


한계 레지스터에 최대 논리적 주소 값을 저장하고 CPU가 논리적 주소를 요청할 때마다 한계 레지스터 값보다 작은 값인지를 검사하게 되고 만약 한계 레지스터 보다 크면 memory protection fault를 발생시킵니다.

 

그렇다면 한번 생각해보겠습니다.


프로세스는 고유한 주소 공간을 가지고 있고 논리적 주소 값은 프로세스마다 독립적으로 할당된다고 했습니다. 예를 들어 프로세스 A에도 100번 논리 주소가, 프로세스 B에도 100번 논리 주소가 있을 수 있다는 것이죠. 그렇지만 프로세스 A의 100번 논리 주소에 매핑되는 실제 물리적 주소와 프로세스 B에 매핑되는 실제 물리적 주소는 다를 겁니다.


따라서 MMU기법에서는 context switching 이 일어날 때마다 Relocation Register의 값을 바뀌는 프로세스에 해당되는 값으로 재설정을 해줘야 하겠죠?

 

4. 정리

 

이번 시간에는 메모리를 어떻게 관리하는지, 메모리 주소를 어떻게 바인딩하는지, MMU가 무엇인지 등등에 대해 살펴봤습니다.

 

다음 시간에는 위의 Contiguous allocation 설명 뒷부분에서 잠깐 언급했었던 Fragmentation이 무엇인지, Paging기법이 무엇인지에 대해서 알아보겠습니다.

 

감사합니다!

 

 

 

 

반응형