정보공간_1

[6기 강북 홍진우] 64비트 멀티코어 OS#3 - 메모리 관리 기법 본문

IT 놀이터/Elite Member Tech & Talk

[6기 강북 홍진우] 64비트 멀티코어 OS#3 - 메모리 관리 기법

알 수 없는 사용자 2014. 10. 10. 21:04

엘리트멤버 6기, 강북멤버십 23-1기 홍진우입니다.

어느덧 가을이네요. 이제 밤이되면 찬바람이 불어오기 사작했습니다.

감기 걸리지 않도록 건강 관리 유의하시기 바랍니다.

그럼 세번째 포스팅 시작하겠습니다!!


 세번째 포스팅에서는 x86-64 코어 기반 64비트 운영체제에서 어떻게 메모리구조가 짜여져 있으며, 어떤 식으로 메모리를 관리하는지 세가지 운영모드별로 나누어 공부해보도록 하겠습니다. 


1. 메모리 관리 기법의 종류

x86-64프로세서에서 지원하는 메모리 과리 기법은 크게 두 가지로 나누어 볼 수 있습니다. 바로 페이징과 세그먼테이션인데요. 두 방식 모두 주소 공간을 특정 단위로 나눈다는 점에서는 같지만, 나누는 방식에 차이가 존재합니다.


 1.1 페이징(Paging) 

   페이징은 메모리를 메모리의 목적이나 용도, 의미를 고려하지 않고 모두 같은 크기의 블록으로 나누어 메모리를 운용하는 기법입니다. 이때 나누게되는 단위 블록 하나 하나를 페이지(Page)라고 부르게 됩니다. OS구동 시 메모리 자원을 프로세스가 요구로 할 시에, 페이지 단위로 메모리를 구분하고 할당하게 됩니다. 따라서 프로세스 간 메모리 보호가 용이하고 페이지들간의 외부 단편화 현상은 없지만, 페이지 블록 내부 단편화 현상이 발생 할 수 있습니다. 


 또한 페이징은 페이지 블록 단위로 메모리에 접근하기 때문에, 목적 데이터가 해당 페이지 않을 경우 페이지 폴트(Page Fault)를 보내고 다른 페이지에 접근하도록 유도하게 됩니다.


 1.2 세그먼테이션(Segmentation)

 메모리를 서로 크기가 다른 단위인 세그먼트(Segment)로 분할하고 메모리를 할당하는 방식입니다. 각 세그먼트 간 크기가 다르기 때문에 페이징처럼 사전에 메모리를 나누어 놓는 것은 불가능하며, 메모리 적재 시에 할당하게 됩니다.. 세그멘테이션 기법을 사용할 경우, 오프셋(Offset)을 기준으로 하여 데이터를 다루기 때문에, 페이징과 달리 각 데이터들이 메모리 어디에 위치해있는지 따로 테이블이 필요하지 않습니다. 



2. 운영 모드 별 메모리 관리 방식

 2.1 리얼 모드의 메모리 관리 방식


  리얼 모드는 최대 1MB의 주소 공간을 사용하며 세그먼테이션 기법만을 사용합니다. 리얼 모드의 세그먼트 크기는 64KB로 고정되어 있으며, 시작 주소(Base Address)는 세그먼트 레지스터로 직접 설정 가능 합니다.



[세그먼트 레지스터와 물리주소의 관계]



 리얼 모드에서는 세그먼테이션의 주소가 바로 물리 주소가 됩니다. 또한, 16비트의 세그먼트/범용 레지스터의 값에 16을 곱한 값을 세그먼트의 기준 주소로 사용함으로써, 16비트 레지스터로 전체 1MB의 주소 공간에 접근이 용이하도록 구성되어 있습니다.



[리얼 모드의 주소 계산 방식]


 세그먼트의 크기가 64KB인 이유는 이와 같이, 리얼 모드에서 사용하는 범용 레지스터의 크기가 16비트이기 때문입니다. 따라서 어드레싱할 수 있는 범위가 0 ~ 65536(0xFFFF)가 됩니다. 



 2.2 보호 모드의 메모리 관리 방식

  보호 모드는 세그먼테이션, 페이징 두 가지 기법을 모두 사용합니다. 보호 모드의 세그먼테이션은 세그먼트 레지스터에 디스크립터(Descriptor)라는 자료구조의 위치(Offset)을 설정합니다. 따라서 세그먼트 레지스터라는 이름 대신 세그먼트 셀렉터(Segment Selector)로 이름을 바꾸어 부릅니다.

 여기서 디스크립터(Descriptor)란, 메모리 영역의 정보를 저장하는 자료구조를 뜻합니다. 세그먼트에 대한 정보를 나타내는 세그먼트 디스크립터는 세그먼트의 시작 주소, 권한, 타입 등의 정보를 가지고 있습니다.


[세그먼트 디스크립터의 구조]


 보호 모드에서 세그먼트 레지스터는 세그먼트 디스크립터의 위치를 가리키며, 세그머트 디스크립터는 GDT(Global Descriptor Table)이라는 테이블에 모여 있습니다. GDT는 여러 개의 디스크립터 들로 이루어져 있으며, 최대 8192개의 디스크립터를 가질 수 있습니다. 


 보호모드에서는 리얼 모드와 마찬가지로 세그먼트 레지스터의 기준 주소에 범용 레지스터의 값을 더해 구하며 주소를 계산하며, 계산된 결과는 선형적인 주소이며, 이를 기반으로 물리주소를 계산합니다. 하지만 보호모드에서는 리얼 모드와 달리 세그먼트의 크기를 지정해줄 수 있기 때문에, 세그먼트의 크기는 해당 세그먼트의 어드레스에 접근할 때 참조하며, 기준 주소(Offset)에 더해질 값은 세그먼트의 크기를 넘지 못합니다. 만약 기준 주소에 더한 값이 세그먼트의 전체 크기를 넘게 되면, 오류가 발생하게 됩니다.



[보호모드에서 세그먼트 셀렉터, 디스크립터, 선형 주소와의 관계]


 리얼 모드와 달리 세그먼테이션을 거쳐 나온 선형 주소는 물리 주소와 일치할 수 도, 일치하지 않을 수 도 있습니다. 선형 주소는 이후에 나올 페이징의 입력 값이 되며, 페이징을 사용하지 않을 시 선형 주소는 물리주소와 1:1대응합니다. 페이징을 사용함으로써, 물리메모리 크기보다 더 큰 영역의 선형 주소도 물리 페이지만 연결하면 상요이 가능하며, 주소 공간을 더 넓게 사용할 수 있는 장점이 있습니다. 보호 모드에서 페이징을 수행하는 방식은 물리메모리를 4KB으로 3단계구분하는 방식과 4MB로 2단계 구분하는 방식 이렇게 두 가지가 있습니다. (프로세서의 물리 주소 확장 기능을 사용하면 다른 방식으로 변경이 가능합니다.)


 2.3 IA-32e 모드의 메모리 관리 방식

 IA-32e 모드는 호환 모드와 64비트 모드가 있습니다. 호환 모드는 보호 모드와 동작이 같습니다. 따라서 64비트 모드에 대해 설명하도록 하겠습니다. 64비트 모드의 최대 사용 가능한 어드레스는 2의 64승인 16EB(Exa Byte)까지 입니다. 기존의 보호 모드보다 비교도 안될 정도로 큰 공간을 가지고 있지만, 메모리 관리 기법은 거의 같으나,  다만 세그먼테이션을 수행하는 기법에서의 차이점들이 있습니다.


 먼저, 세그먼트 디스크립터에 설정된 기준 주소와 상관없이 모든 세그먼트가 기준 주소는 0, 크기는 64비트 전체로 설정된다는 것입니다. 따라서  IA-32e모드에서는 선형 주소를 다른 여러 개의 세그먼트로 구분할 수 없는 점을 기억해두셔야합니다. 그리고 두 가지의 서브 모드를 지원하므로 이를 구분하고자 코드 세그먼트 디스크립터에 따로 구분가능한 비트필드를 추가되 있다는 점이 있습니다. 이 필드를 통해 굳이 모드를 변환하지 않아도 32비트 코드를 실행하는 것이 가능합니다.


[IA-32e모드에서 세그먼트 셀렉터, 디스크립터, 선형주소]


또한 페이지 테이블은 어드레스가 늘어난 만큼, 4KB 페이지는 5단계, 2MB 페이지는 4단계로 변경됩니다.




 지금까지 각 모드별 메모리 관리가 어떻게 이루어지는 지 훑어보았습니다. 각 테이블과 디스크립터, 레지스터의 세부 계산 원리는 매우 복잡하고 어렵습니다.  더욱 상세한 정보에 대해 호기심이 생기신다면, 께서는 x86-64 코어 관련 데이터시트나, MS사의 정보를 참조하시면 상세 자료를 얻으실수 있습니다.



 다음 포스팅은 [64비트 멀티코어 OS#4 - 부트 로더] 편입니다!



* 참조 자료 : '64비트 멀티코어 OS 원리와 구조' - 한승훈 저