글로벌 설명자 표
Global Descriptor Table이 글에는 여러 가지 문제가 있다.이 문제를 개선하거나 대화 페이지에서 토의하십시오.(이러한 템플릿 메시지를 제거하는 방법 및 시기 알아보기)
|
GDT(Global Descriptor Table)는 기본 주소, 크기, 실행성, 쓰기성 등의 액세스 권한 등 프로그램 실행 시 사용되는 다양한 메모리 영역의 특성을 정의하기 위해 인텔 x86 패밀리 프로세서가 80286부터 사용하는 데이터 구조다.이러한 기억 영역은 인텔 용어로 세그먼트라고 불린다.
글로벌 설명자 표
GDT는 세그먼트 설명자 이외의 것도 담을 수 있다.GDT의 모든 8바이트 항목은 설명자지만, 이러한 설명자는 메모리 세그먼트뿐만 아니라 태스크 상태 세그먼트(TSS), 로컬 설명자 테이블(LDT) 또는 메모리의 호출 게이트 구조를 참조할 수 있다.마지막 Call Gates는 x86 특권 수준 간의 제어권 이양에 특히 중요하다. 비록 이 메커니즘은 대부분의 현대 운영 체제에서 사용되지 않지만 말이다.
LDT(Local Descriptor Table)도 있다.여러 개의 LDT를 GDT에서 정의할 수 있지만, 단 한 번에 하나의 LDT만 현재 작업과 연관된다.LDT는 특정 프로그램에 비공개적인 메모리 세그먼트를 포함하고 있는 반면, GDT는 글로벌 세그먼트를 포함하고 있다.x86 프로세서는 특정 머신 이벤트에서 현재의 LDT를 자동으로 전환하는 기능이 있지만 GDT를 자동으로 전환하는 기능은 없다.
프로그램이 수행할 수 있는 모든 메모리 액세스는 항상 세그먼트를 통과한다.80386 프로세서 이상에서는 32비트 세그먼트 오프셋 및 제한 때문에 세그먼트가 주소 지정 가능한 전체 메모리를 커버하도록 하는 것이 가능하여 사용자에게 세그먼트 상대 어드레싱을 투명하게 할 수 있다.
세그먼트를 참조하기 위해 프로그램은 GDT 또는 LDT 내부의 인덱스를 사용해야 한다.그러한 지수를 세그먼트 선택기(또는 선택기)라고 한다.선택기는 일반적으로 사용할 세그먼트 레지스터에 로드되어야 한다.GDT와 인터럽트 설명자 테이블(IDT)의 위치를 설정/획득할 수 있는 기계 지침과는 별도로 메모리에 메모리를 참조하는 모든 기계 지침에는 암묵적인 세그먼트 레지스터(가끔 2개)가 있다.대부분의 경우 이 세그먼트 레지스터는 명령 앞에 세그먼트 접두사를 추가하여 재정의할 수 있다.
세그먼트 레지스터에 선택기를 로드하면 GDT 또는 LDT가 자동으로 판독되고 프로세서 자체 내에 세그먼트의 속성이 저장된다.GDT 또는 LDT에 대한 후속 수정은 세그먼트 레지스터를 다시 로드하지 않는 한 효과적이지 않다.
GDT 예제
아래는 4GB의 사용 가능한 메모리를 모두 여는 GDT의 어셈블리 구현이다.
- 기본 = 0x00000000, 세그먼트 제한 = 0xffffffffff
; 오프셋 0x0 .cs 서술자: dq 0 ; 오프셋 0x8 .code: ; cs는 이 설명자를 가리켜야 한다. 드와 0xffff ; 세그먼트 제한 첫 번째 0-15비트 드와 0 ; 기본 첫 번째 0-15비트 db 0 ; 기본 16-23비트 db 0x9a ; 액세스 바이트 db 11001111b ; 하이 4비트(하이 4비트) 로우 4비트(하이 4 마지막 비트)(하이 4비트 폭) db 0 ; 기본 24-31비트 ; 오프셋 0x10 .data: ; ds, ss, es, fs 및 gs는 이 설명자를 가리켜야 한다. 드와 0xffff ; 세그먼트 제한 첫 번째 0-15비트 드와 0 ; 기본 첫 번째 0-15비트 db 0 ; 기본 16-23비트 db 0x92 ; 액세스 바이트 db 11001111b ; 하이 4비트(하이 4비트) 로우 4비트(하이 4 마지막 비트)(하이 4비트 폭) db 0 ; 기본 24-31비트 64비트 GDT
GDT는 여전히 64비트 모드로 존재하며, GDT는 정의되어야 하지만 일반적으로 변경되거나 분할에 사용되지 않는다.레지스터의 크기는 48비트에서 80비트로 확장되었으며, 64비트 선택기는 항상 "플랫"이다(즉, 0x00000000000000000000 ~ 0xFFFFFFFFFF).단, FS와 GS의 베이스는 0으로 제약되지 않고, 프로세스 환경 블록, 스레드 정보 블록 등 아이템의 상쇄를 위한 포인터로서 계속 활용되고 있다.
시스템 비트(액세스 필드의 4번째 비트)를 지우면 설명자의 크기는 8이 아닌 16바이트가 된다.코드/데이터 세그먼트를 무시해도 TSS는 그렇지 않지만 TSS 포인터의 길이가 64비트일 수 있어 설명자가 TSS 포인터의 높은 dword를 삽입할 수 있는 공간이 더 필요하기 때문이다.
64비트 버전의 Windows(윈도우)에서는 GDT 후크를 금지하고 있으며, 이를 시도하면 기계가 버그 검사를 받을 수 있다.[1]
로컬 설명자 테이블
LDT(Local Descriptor Table)는 GDT: 주소가 선형 메모리, 크기, 실행성, 쓰기성, 액세스 권한, 메모리의 실제 존재 등에서 시작되는 것과 마찬가지로 보호 모드에서 x86 아키텍처에 사용되는 메모리 테이블이다.
LDT는 Global Descriptor Table(GDT)의 형제자매로서, 각각 프로그램에서 액세스할 수 있는 최대 8192개의 메모리 세그먼트를 정의한다. - 참고로 GDT와 달리 0eth 항목은 유효한 항목이며, 다른 LDT 항목과 마찬가지로 사용할 수 있다.또한 GDT와 달리 LDT는 특정 시스템 항목을 저장하는 데 사용할 수 없다.TSS 또는 LDT.그러나 콜 게이츠와 태스크 게이츠는 괜찮다.
역사
인텔 80286처럼 페이징 기능이 없는 x86 프로세서에서는 LDT가 여러 프로세스에 대해 별도의 주소 공간을 구현하는 데 필수적이다.일반적으로 비공개 보유 메모리를 기술하는 사용자 프로세스당 하나의 LDT가 존재하며, 공유 메모리와 커널 메모리는 GDT가 기술한다.운영 체제는 새로운 공정 스케줄링, LLDT 기계 지침 또는 TSS 사용 시 현재 LDT를 전환한다.반대로 GDT는 일반적으로 전환되지 않는다(VMware와 같은 가상 머신 모니터가 컴퓨터에서 실행 중인 경우 이러한 현상이 발생할 수 있다).
두 표 사이의 대칭성의 결여는 현재의 LDT가 특정 이벤트, 특히 TSS 기반 멀티태스킹을 사용하는 경우 자동으로 켜질 수 있지만 GDT에서는 이것이 가능하지 않다는 사실에 의해 강조된다.또한 LDT는 특정 유형의 메모리 세그먼트(예: TSSes)를 저장할 수 없다.마지막으로, LDT는 실제로 GDT 내부의 설명자에 의해 정의되는 반면, GDT는 선형 주소에 의해 직접 정의된다.
GDT를 통해 공유 메모리를 만드는 것은 몇 가지 단점이 있다.특히 그러한 기억은 모든 과정과 동등한 권리로 볼 수 있다.가시성을 제한하고 공유 메모리의 보호를 차별화하기 위해, 예를 들어 일부 프로세스에 대해 읽기 전용 액세스만 허용하려면 동일한 물리적 메모리 영역을 가리키고 지정된 공유 메모리 영역에 대한 액세스를 요청한 프로세스의 LDT에서만 별도의 LDT 항목을 사용할 수 있다.
동일한 메모리 영역을 가리키는 LDT(및 GDT) 항목을 별칭이라고 한다.또한 별칭은 일반적으로 코드 세그먼트에 대한 쓰기 액세스 권한을 얻기 위해 생성된다. 실행 가능한 선택기는 쓰기에 사용할 수 없다. (모든 것이 동일한 메모리 세그먼트에 위치하는 소위 작은 메모리 모델에서 구성된 보호 모드 프로그램은 코드와 데이터/스택에 대해 별도의 선택기를 사용해야 하며, 두 선택기를 기술적으로 만든다."별칭도").GDT의 경우 TSS와 같은 시스템 세그먼트에 접근하기 위해 별칭도 생성된다.
세그먼트에는 설명자에 "현재" 플래그가 있어, 필요할 경우 메모리에서 제거할 수 있다.예를 들어, 코드 세그먼트 또는 수정되지 않은 데이터 세그먼트는 폐기할 수 있으며, 수정된 데이터 세그먼트는 디스크로 스왑 아웃할 수 있다.단, 전체 세그먼트를 하나의 단위로 운영해야 하기 때문에 스와핑이 적시에 이루어질 수 있도록 규모를 제한할 필요가 있다.그러나 더 작고 쉽게 스왑할 수 있는 세그먼트를 사용하면 세그먼트 레지스터를 더 자주 다시 로드해야 하며, 이는 그 자체로 시간이 많이 걸리는 작업이다.
현대적 용법
Intel 80386 마이크로프로세서는 디스크 페이징이 세그먼트 스와핑보다 훨씬 빠르고 효율적이라는 이점과 함께 별도의 물리적 메모리 페이지(그들 자신들만의 매우 작은 메모리 단위)를 동일한 가상 주소에 할당하는 페이징을 도입했다.따라서 현대의 32비트 x86 운영 체제는 주로 레거시 16비트 코드를 실행하는 데 LDT를 거의 사용하지 않는다.
16비트 코드가 메모리를 공유하는 동안 32비트 환경에서 실행되어야 하는 경우(예: OS/2 2.0 이상에서 OS/2 1.x 프로그램을 실행할 때), LDT는 모든 플랫(페이징) 주소에도 선택기가 있도록 작성되어야 한다(일반적으로 이 경우 LDT는 64KiB 항목으로 채워진다).이 기술을 LDT 타일링이라고도 한다.LDT의 제한된 크기는 가상 플랫 주소 공간이 512메가바이트(8191 곱하기 64KiB)로 제한되어야 함을 의미한다. 이는 버전 4.5에서 제한되었지만 OS/2에서 일어나는 일이다.또한 32비트 환경에 할당된 개체가 64KiB 경계를 넘지 않도록 해야 한다. 이는 주소 공간 낭비를 발생시킨다.
32비트 코드가 임의 메모리 개체를 16비트 코드에 전달할 필요가 없는 경우(예: 윈도우즈 NT 또는 윈도우즈 3.1 에뮬레이션 계층에 존재하는 OS/2 1.x 에뮬레이션)에는 32비트 주소 공간의 크기를 인위적으로 제한할 필요가 없다.
참조
- ^ "Patching Policy for x64-Based Systems".
If the operating system detects one of these modifications or any other unauthorized patch, it will generate a bug check and shut down the system.
외부 링크
- Intel Architecture 소프트웨어 개발자 설명서
- GDT 표 OSDev.org
- OSDev.org의 GDT 자습서
- Bran's Kernel Dev GDT 자습서
- BreakThorn 보호 모드