2011. 6. 13. 09:45

Paging


Segmentation 에 의해 생성된 32 bit의 Linear Address는 4GB까지 지정할 수 있다.
이런 Linear Address를 사용하여 페이징 절차를 거치면 Memory의 Physical 주소를 얻을 수 있다.
그럼 이런 Paging은 어떤 단계로 이루어지는지 알아보도록 하자
[그림 1] Paging

Paging을 하는 단계는 다음과 같다.
1)  32 bit의 선형주소를 Page Directory Index, Page Table Index, Offset의 3부분으로 나눈다.
2) CPU의 CR3 레지스터가 가리키고 있는 페이지 디렉토리와 선형주소로 부터 얻은 페이지 디렉토리 인덱스를 사용하여 페이지 테이블의 포인터를 얻는다.
3) 페이지 테이블의 포인터와 선형 주소의 페이지 테이블 인덱스를 사용하여 실제 물리 주소의 페이지를 얻는다.
4) 실제 물리 주소의 페이지에 오프셋을 더하여 최종적인 물리 주소를 얻는다.

그럼 각각에 대해 알아보자

1. Control Registry3
[그림 2] Control Register3
그림 2와 같이 다양한 레지스터 중 Page에 사용되는 레지스터는 CR3(Control Register3)입니다.
Page-Directory Base는 다른말로 Page Directory의 PFN(Page Frame Number)라고 불립니다.
해당 위치에 CR3가 가르키는 Page Directory의 주소가 저장되어 있습니다.

OS에서 CR3는 매우 중요한 역할을 하는데 해당 레지스터에 의해 각각의 프로세스가 독립적인 메모리 주소 공간을 가질 수 있기 때문이다.
이 말은 Process Switching이 일어날 때 Process는 메모리 페이지를 변경해야 합니다.
왜냐 하면, 연산해야하는 대상이 변경되기 때문에 연산 대상이 변경되어지면 당연히 연산 대상의 데이터도 변경되어야 하기 때문입니다.
CR3에서는 Page-Directory Base 의 주소를 변경함으로써 간단하게 해당 일을 처리할 수 있습니다.

2. Page Directory, Page Table

[그림 3] Page Directory, Page Table

(1) Page Directory
페이지 디렉토리는 32비트 페이지 디렉토리 엔트리 정보를 1024개 가지고 있는 배열 형태이며 하나의 프로세스는 반드시 하나의 페이지 디렉토리가 존재해야 합니다.

CR3의 Page-Directory Base에는 Page Directory의 시작 주소가 적혀 있으므로 해당 주소를 찾아가면 Page Directory의 시작 주소를 얻을 수 있습니다.
그럼 Page Directory의 1024개 중 어떤 값을 사용할지는 어떻게 알 수 있을까요?
그 방법은 세그멘테이션에서 작성된 Linear Address의 22~31비트에 몇번째 값인지 나와 있습니다.
0000000001 값인 경우 배열 1이므로 2번째 값이 해당 값이 됩니다.

1024개인 이유는 하나의 필드가 4MB를 표현하므로 4GB를 인식하기 위해선 1024개가 필요하게 됩니다.
(참고 : Windows에서는 PDE와 PTE를 0xC0000000~0xC03FFFFF에 매핑하고 있음)

(2) Page Table
page table은 페이지 디렉토리에서 페이지의 PFN을 가져와 시작주소를 가르키게 됩니다.
그리고 페이지 디렉토리와 동일하게 Linear Address의 11~21비트에서 몇번째 값을 가져올지 정하게 됩니다.
이렇게 가져온 값은 실제 물리 메모리의 4KB Page의 시작 주소를 나타내게 되며 Linear Address의 0~11비트의 offset 값이 더해져 실제 물리 주소를 나타내게 됩니다.

3. 공유 메모리와 공유 모듈
Windows에서는 동일한 DLL을 여러개의 프로세스에서 공유되어 사용하는 경우가 많습니다.
이런 DLL을 매번 메모리에 올린다면 메모리 낭비가 심하게 됩니다.
그렇기 때문에 Windows에서는 메모리 낭비를 막기 위해 동일한 DLL에 대해 하나의 DLL을 실제 물리적 메모리에 올리고 모든 프로세스는 해당 DLL을 공유하는 형태로 사용하고 있습니다.

이럴 경우 생각해볼 문제가 A라는 Process는 처음 올라간 DLL을 그대로 사용하지만 B라는 Process는 올라간 내용 중 특정 부분을 수정하는 경우가 있을 수 있습니다.
이런 문제를 해결하기 위해 Windows에서는 Copy-On-Write라는 개념을 사용합니다.
즉, Process가 변경해야하는 경우 해당 Page를 copy하여 copy한 곳에 변경 내용을 쓰는 방식입니다. 이런 방식으로 공유 DLL에 대해 문제 없이 사용할 수 있습니다.

이런 경우 다른 문제가 발생할 수 있습니다.
만일 본래의 page를 써야하는 경우에 해당 내용은 변경이 되었으므로 원래 값의 위치를 알 수가 없게 되는 문제가 발생합니다.
Windows에서는 이런 문제를 방지하기 위해 Prototype Page Table Entry(PPTE)라는 개념을 사용합니다.
해당 개념은 DLL원본의 위치를 저장하는 공간을 따로 두어 만일 원복을 해야하는 경우가 생기는 경우 사용하도록 하고 있습니다.

4. 3GB, PAE
(1) 3GB
Windows에서는 4GB 가상메모리를 2GB는 User와 Kernel 메모리가 사용할 수 있는 유저모드 나머지 2GB는 Kernel만 사용할수 있는 커널모드로 나누어 사용하고 있습니다.
그런데 만일 프로그램이 수행될때 해당 프로그램이 메모리를 확보한 후 자체에서 해당 메모리를 나누어 사용하는 MS Sql Server같은 프로그램이 수행되는 경우 유저모드의 메모리가 많이 필요한 경우가 있습니다.
이런 경우 해당 유저모드의 메모리를 3GB까지 늘려주는 옵션이 3GB입니다.
[그림 4] 3GB

그림 4와 같이 메모리 구조가 변경되게 되며 Windows 자체에서 해당 내용을 인지하여 메모리를 사용하게 됩니다.

(2) PAE(Page Address Extensions)
[그림 5] PAE
PAE는 실제 물리 메모리가 많이 필요한 경우 Physical Memory 인식을 늘려주기 위한 방법이다.
32Bit의 경우 4GB까지 인식할 수 있으므로 메모리가 늘어나도 4GB까지 인식하게 된다.

실제 Paging의 그림과 그림5를 비교해 보면 Page Directory Pointer Table이 생긴걸 알 수 있다.
즉 해당 단계에 4개의 Pointer Entry를 추가함으로써 36Bit의 물리적 주소를 지정할 수 있게 된다.
2^36 = 64GB이므로 64GB까지 확장하여 지원할 수 있게 된다.

3GB와 PAE는 동일하게 boot.ini파일에 /3GB /PAE로 추가한 후 리부팅을 하면 적용되게 된다.

위와같이 Paging은 프로세서에서 가상메모리를 가공하여 만든 Linear Address를 이용하여 물리적 메모리와 메핑하는 작업이며 메핑을 하는데 많은 구조가 있다는 것을 알 수 있을 것이다.


* 자료출처
http://rockball.tistory.com/125