제가 나름대로 정리해본 Physical Memory 와 Virtual Memory 에 대한 내용

페이징

페이지 테이블 : 프로세스의 메모리가 실제 메모리와 어떻게 매핑되어 있는지를 나타내는 정보 목록

페이지 테이블 중 페이지 디렉토리만 메모리에 올려놓고 페이지 테이블 인덱스는 필요시에만 올려 놓음

CR3 레지스터 사용하여 Page directory 의 address 를 구한다.

 

세그먼트

동일한 속성을 가지는 data 영역으로 메모리를 나눠서 관리하는 방식

세그먼트는 세그먼트 디스크립터 테이블을 참조하여 해당 세그먼트의 시작 주소를 가져온다.

주소가 한계치를 넘는지 접근권한이 있는지 확인하여 문제 있으면 trap 발생한다.

최초의 세그먼트는 16Bit address 를 사용하여 1M(20Bit) 의 주소를 가리키기 위해 사용됨

386의 보호모드가 적용된 이후 address 를 가리키는 용도가 아닌 접근가능 메모리 범위 지정 등의 용도로 쓰인다.

GDTR/LDTR 레지스터를 사용하여 세그먼트 디스크립터 접근 가능 (여기서 얻은 디스크립터 주소에 CS,DS 와 같은 레지스터에 있는 Index 값 사용해서 세그먼트값 얻는다.)

세그먼트 레지스터는 인덱스만 가지고 실제 정보는 세그먼트 디스크립터에 있다.
Logical (virtual) address -> segmentation (세그먼트 레지스터 + 메모리 주소 : CS:1234) -> Linear address -> paging (page directory + page table + offset) ->
Physical address

세그먼트 디스크립터는 모든 테스크에 전역적으로 존재할 수 있는 그룹과 어떤 한 테스크에 종속적으로 존재할 수 있는 그룹이 있을 수 있다.

GDT(Global Descriptor Table) 모든 프로그램이 참조하는 테이블 OS 에서 반드시 만들어야 한다.

LDT(Local Descriptor Table) 각 테스크 단위에서 정의해서 사용하는 것 반드시 만들 필요는 없으며 NT 계열에서는 일반적으로 정의 하지 않고 16Bit 에뮬레이션에서만 사용

 

1: kd> dg 0 255

P Si Gr Pr Lo

Sel Base Limit Type l ze an es ng Flags

---- -------- -------- ---------- - -- -- -- -- --------

0000 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000

0008 00000000 ffffffff Code RE Ac 0 Bg Pg P Nl 00000c9b

0010 00000000 ffffffff Data RW Ac 0 Bg Pg P Nl 00000c93

0018 00000000 ffffffff Code RE Ac 3 Bg Pg P Nl 00000cfb

0020 00000000 ffffffff Data RW Ac 3 Bg Pg P Nl 00000cf3

0028 f773ffe0 000020ab TSS32 Busy 0 Nb By P Nl 0000008b

0030 f773f000 00001fff Data RW Ac 0 Bg Pg P Nl 00000c93

 

1: kd> r

Last set context:

eax=80800000 ebx=028c4000 ecx=a2b3d020 edx=000d9000 esi=a2b3cf68 edi=a35c1004

eip=b8c4952e esp=b76c59cc ebp=b76c5a08 iopl=0 nv up ei pl nz na po nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010202

 

0008 은 1000 이고 뒤에서 세 번째 비트가 0 이므로 GDT (1 이면 LDT) 이고 Index 가 1 이므로 두 번째 디스크립터 를 가리킨다.

FS 레지스터는 TIB(Thread Information Block) 을 가리킨다.

TIB 에는 Exception handler 정보, Stack 시작주소 Stack 마지막 주소 등이 들어 있다.

페이지 디렉토리의 위치 정보는 CR3 레지스터의 11비트에서 31비트 사이의 20비트를 통하여 얻어내게 된다.

CR3 레지스터에 저장되어 이쓴 20비트의 페이지 디렉토리 PFN(Page Frame Number)은 실제 물리적 주소를 나타내는 것이 아니며 물리적 주소의 페이지 프레임 번호 (Page Frame Number) 를 저장하고 있는 것이다.
실습

lkd> !pte 10000000
               VA 10000000
PDE at   C0300100        PTE at C0040000
contains 2F48F867      contains 5A15A025
pfn 2f48f ---DA--UWEV    pfn 5a15a ----A--UREV

lkd> !pfn 2f48f
    PFN 0002F48F at address 81C6ED68
    flink       000006F5  blink / share count 00000017  pteaddress C0300100
    reference count 0001   Cached     color 0
    restore pte 00000080  containing page        07302F  Active     M      
    Modified             
lkd> !pfn 5a15a
    PFN 0005A15A at address 82072070
    flink       000005AC  blink / share count 00000011  pteaddress E2DE2448
    reference count 0001   Cached     color 0
    restore pte EB73F428  containing page        05F019  Active      P     
      Shared

PPTE
Windows는 공유된 DLL 또는 메모리 맵에 의하여 파일이 공유되어질 때 PPTE (Prototype Page Table Entry) 를 만든다.
PPTE 는 마이크로프로세서에서 메모리 변환에 사용되기 위한 용도가 아닌 공유하고 있는 메모리 맵드 파일 또는 공유된 DLL 에 대하여 Windows 에서 본래의 위츠를 이 별도의 PPTE 를 통하여 관리하고 있는 것이다.

PAE
PAE 를 사용할 경우 첫 2 비트가 PageDirect Index 로 사용되고 10Bit 로 되어 있던 PFN 이 9Byte 로 변경되어 4GB 이상의 메모리를 사용할 수 있다.
실제 4GB 메모리를 사용할 경우 물리 메모리의 일부를 다른 장치가 사용하여 3.2GB 의 메모리만 사용할 수 있는 경우가 발생하는데 이때 PAE 를 꼭 사용해야 전체 메모리를 사용할 수 있다.
PAE 를 설명할 때 일반적으로 사람들은 Page 단계가 2단계에서 3단계로 늘어난 것에 촛점을 맞추어 설명한다. 즉 1024*1024*4KB 이던 것이 4*512*512*4KB 즉 Page Directory 와 Page Table Index 가 1024 에서 512 로 변경되고 Page Directory 가 1개에서 4개로 늘어난 것에 촛점을 맞춘다. 그러나 실제로 중요한 것은 모든 Process 들이 4GB 의 가상메모리를 사용하고 그 가상 메모리가 실제 물리 메모리에 매핑되어야 할때 물리 메모리가 부족하다는 것이다. 그래서 PAE 를 설정하면 PageDirectory 와 Page Table 에 저장되어 있는 물리 메모리가 4GB 영역을 넘어선 물리 메모리를 가리킬 수 있어 다수의 Process 의 가상메모리가 실제 물리 메모리에 매핑될 수 있는 것이다.