Virtual Address (가상 메모리의 구현 ) - 세그먼트와 페이징 기법
메모리의 효율적인 관리와 사용을 위한 세그먼트와 페이징 기법
실제 메모리 접근 과정의 간략한 설명
실제 메모리의 값을 접근하기 위해서는 위에서 보여지는 작업이 이루어진다. 만약에 코드를 읽어야 한다면 Segment Selector라고 있는 부분이 CS(Code Segment)레지스터가 되며 Offset은 IP(Instruct Pointer )가 된다. CS레지스터를 Segment Selector라고 부르는 이유는 CS레지스터가 Descriptor 테이블의 인덱스만 가지고 있는 것이 아니라 다른 정보를 가지고 있기 때문이다. 그 외에도 Segment Descriptor를 요구 할 때의 특권 등이 들어가 있다. CS의 상위 13bit가 Descriptor 테이블의 인덱스가 되며 그렇게 가져온 Segment Descriptor는 64bit의 세그먼트 정보가 들어가 있다. 일차적으로 Segment Base Address가 여러 비트열로 나눠 저장되어있으며 Segment Base Address와 위에서 말한 IP가 더해지며 선형 메모리 공간(Linear Address Space)의 주소가 된다. 거기서 나온 값은 또다시 PageDir, PageTable, Offset으로 구성되어있는데 위의 PageDir의 시작주소는 CR3레지스터가 가지고 있으며 PageDir의 값은 인덱스가 된다. 그 값은 다시 테이블의 시작주소가 되며 PageTable은 다시 인덱스가 된다. 거기서 나온 값은 실제 메모리 주소의 4Kb의 페이지의 시작주소가 되며 Offset을 더해 접근해야 하는 실제 메모리 주소가 된다.
세그먼트 레지스터(Segment Selector)
세그먼트 레지스터는 위의 그림과 같이 구성되어 있어서 세그먼트 셀렉터라고 불린다. 세그먼트 디스크립터의 인덱스 영역이 13bit, TI가 1bit, RLP은 디스크립트를 통해 요구할 때의 특권레벨을 3bit를
사용한다. 개요에서 설명되어 있는 부분을 더 붙이면
GDT(Global Descriptor Table)과 LDT(Local Descriptor
Table)을 선택할 기준이 TI값이 0이면 GDT 1이면 LDT가 선택된다.
세그먼트 디스크립터(Segment Descriptor)
세그먼트 레지스터를 통해서 세그먼트 디스크립터를 가져오며 64bit의 비트열로 구성되어 있으며 여러 플래그값과 Segment Base Address를 포함하고 있다.
Base – 두 부분으로 나눠져 있으며 합치면 32bit의 Segment Base Address가 된다.
Limit – 두 부분으로 나눠져 있으며 합치면 20bit가 된다. 이것은 세그먼트의 허용하는 메모리 범위를 지정하게 하는데 20bit면 1Mb밖에 지정할 수 없게 된다. 여기서 G 플래그가 사용되는 데 G 프래그가 1로 세팅되면 기본단위가 4Kb가 되며 4Gb를 모두 지정할 수 있게 된다. 즉 호환을 위해서 이렇게 처리되는 부분이다.
S(System) – 44번 비트인 S는 시스템 비트라고 하여 코드 세그먼트, 테이터 세그먼트, 스택 세그먼트 등으로 사용된다.
다른 플래그는 시스템 프로그래밍에 크게 중요하지 않아 생략한다.
Offset
세그먼트 레지스터 |
Offset |
CS( Code Segment ) |
IP |
SS( Stack Segment ) |
SP, BP |
DS( Data Segment ) |
AX, BX, CX, DX |
ES( Extra Segment ) |
DI |
각 세그먼트에 해당하는
Offset이 정해져 있다. Offset 또한 범용 레지스터를 사용해서 저장되며 어떤 스레드가
대기상태에서 실행상태로 넘어갈 때 이런 레지스터 정보를 프로세서에 넣어주게 된다.
세그먼트 기법
8086 아키텍쳐에서는 16bit 프로세스를 사용하지만 1Mb 메모리 주소를 접근하기 위해 만들어졌다. 세그먼트 레지스터의 Base Segment Address에 4bit 시프트 연산을 한 뒤 Offset을 더하여 만들어진 20bit 주소를 만들어낸 것이다. 32bit 시스템이 일반화된 현재의 CPU 아키텍쳐에서는 불필요하게 보일지라도 시스템의 호환성과 다른 여러가지 정보를 사용하기 위해 지금까지 사용된다.세그먼트로 나누는 것은 위에서 보는 바와 같이 코드영역과 스택 등의 여러 영역을 일괄적으로 할당하고 사용되어지기 보다 유연하게 필요한 만큼 할당하여 사용되길 원했기 때문이다. 하지만 세그먼트로 나누어지면서 실제 메모리는 단편화를 피할 수 없다.
페이징 기법
세그먼트 기법과 페이징 기법을 통해서 가상 주소를 구현하였다. 실제 응용프로그램에서 제공되는 4Gb 메모리는 가상메모리며 그것을 구현하기 위해 세그먼트와 페이징 기법이 사용된다. 세그먼트로만은 메모리의 단편화 문제를 해결할 수 없으며 페이징을 같이 사용하여 응용프로그램의 메모리 요청을 그 시점에 물리주소를 매핑한 가상 메모리주소를 통해서 처리하게 된다. 이렇게 함으로써 응용프로그램에서는 연속되어있는 메모리 주소를 얻어 사용할 수 있지만 실제 메모리 주소는 그렇지 않을 수 있다. 메모리를 사용하기 위해 운영체제에 요청하면 적당한 위치에 실제 메모리를 할당하고 그것을 매핑하여 페이지를 만들게 된다. 그렇게 되면 사용자는 실제 메모리에 대해서 고민하며 설계하지 않아도 되고 운영체제는 페이지 관리에 집중할 수 있다. 만약 실제 물리적 메모리 사이즈가 2Gb이라면 나머지 2Gb는 하드디스크에 저장된다. 만약 페이지 사이즈가 2Gb이고 읽어오려고 하는 데이터가 하드디스크에 있다면 메모리에 있는 데이터를 다시 하드디스크로 옮기고 디스크에 있는 데이터를 메모리에 올리는 작업이 이루어진다. 이것은 엄청난 오버헤드이므로 페이지의 사이즈를 적정사이즈인 4Kb로 정해졌다. 메모리에 올라와있는 페이지인지 확인 후 없을 시 페이지 fault가 돌아오며 다시 페이지를 검색하여 디스크에서 가져오게 된다. 어떤 페이지를 올리고 내리는 결정은 OS에서 처리되며 이 페이지 교체방법은 이 시스템의 효율을 결정하게 된다
'Game programing > System Programing' 카테고리의 다른 글
Stack structure(스택구조) (0) | 2012.11.29 |
---|