9장. 세그먼테이션

  • 선형 메모리 : OS에서 사용자가 지정한 메모리 주소와 세그먼트 레지스터가 합해져서 얻어디는 메모리
  • 세그먼테이션 : 사용자가 지정한 메모리 주소로부터 선형 메모리까지 얻어지는 과정

    • 접근하고자 하는 메모리에 대한 세그먼테이션 과정이 끝나게 되면, 마이크로프로세서는 위 과정에서 얻어진 선형 메모리로 부터 페이징 메커니즘에 의해 물리 메모리 주소를 가지고 온다.
  • 16비트때 적용 되던, Segment : Offset 메카니즘이 32비트, 64비트 이후에도 동일하게 적용 되었다.
  • GDT(Global Descriptor Table) :  모든 프로그램이 참조할 수 있는 세그먼트 디스크립터들의 모임
  • LDT(Local ~ ) : 멀티태스킹 환경에서 각 태스크 단위로 정의할 수 있다. ( 윈도우  NT 계열의 경우 이 LDT를 정의 하지 않고 있다. )
  • GDTR : 디스크립터테이블의 시작 위치( 32bits ), Limit( 16bits, 해당 테이블의 사이즈 - 1 값 )

    • 하나의 디스크립터는 8Bytes, Table Limit = (디스크립터 개수 * 8) - 1 이므로 최대 세그먼트 디스크립터의 개수는 8192( 실제 사용 가능 개수는 8192 = 2^13 - NULL 디스크립터 때문 )
  • 세그먼트 셀렉터

    • Index (상위 13 bits) - 세그먼트 테이블에 있는 디스크립터의 배열에서 어떤 것을 선택할 것인지 나타냄
    • TI (1 bit) - 0 : GDT/ 1 : LDT 를 사용 할지 선택
    • RPL( 2 bits ) - 특권레벨
  • Ntddk.h 에 정의 되어 있는 윈도우의 세그먼트들

    • #define KGDT_NULL 0
    • #define KGDT_RO_CODE 8
    • #define KGDT_R0_DATA 16
    • #define KGDT_R3_CODE 24
    • #define KGDT_R3_DATA 32
    • #define KGDT_R0_PCR 48
    • #define KGDT_R3_TEB 56
    • .....
  • 윈도우의 하위 2GByte( 0 ~ 0x7fff ffff ) : 어플리케이션이 사용, 윈도우의 상위 2GByte( 0x8000 0000 ~ 0xffff ffff ) : 커널레벨에서 사용하는 영역
  • 어플리케이션에서의 세그먼트 레지스터와 내용
    • 코드 세그먼트( 코드영역 ) : 0x1B 윈도우에서는 커널의 메모리에 대한 보호를 세그먼트 디스크립터를 통하여 하고 있지 않기 때문에 0 ~ 0xffff ffff 의 4GB 범위이다. 즉, 이 세그먼트 디스크립터에서는 커널레벨의 메모리 까지 접근을 허용하고 있지만 페이징 과정에서 접근을 허용하지 못하도록 한다.
    • 데이터 세그먼트( 데이터영역 ) : 0x23 베이스 어드레스 가 0, 크기는 0xffff ffff, 즉 4GB 까지 지시할 수 있다.
    • 스택 세그먼트0x23  윈도우의 경우 스택 세그먼트를 위한 별도의 속성을 가지는 디스크립터를 정의하지는 않고 있으며, 어플리케이션의 데이터 세그먼트를 같이 사용하고 있다.
    • FS 레지스터 : 프로그램에 보조적인 용도로 사용 할 수 있도록 추가적으로 제공해 주고 있는 세그먼트. 윈도우즈 어플리케이션 레벨에서는 FS 레지스터를 TIB( Thread Information Block ) 의 영역을 지시하는데 사용하고 있다. TIB 에는 쓰레드에 대한 예외 처리( Exception Handler ) 정보, 스택의 시작 주소, 스택의 마지막 주소 등을 나타내고 있다. 베이스 어드레스는 0x7ffd e000 이며, 즉, fs:0 메모리 가 실제로는 DS:0x7ffd e000 과 일치 한다는 이야기 이다. 유저레벨에서의 FS 세그먼트 레지스터의 베이스 어드레스에는 해당 프로세서의 쓰레드 생성 순서와 매우 중요한 연관 관계를 가진다. FS 의 베이스 어드레스가 0x7ffde000 이며, 두 번째 생성되는 쓰레드의 FS 베이스 어디레스는 0x7ffd d000 이 되며, 세 번째는 0x7ffd c000 이 되며, 그 이후의 주소는 각각 4KByte씩 줄여나가면 된다.
    • 각각의 쓰레드가 FS 세그먼트 0x38을사용하면서 그 세그먼트의 베이스 주소를 다르게 한다는 곳은 윈도우에서 쓰레드 스위칭이 발생할 때 마다 그 내용을 바꿔주고 있다는 의미이다.
  •  커널레벨에서의 세그먼트 레지스터와 그 내용
    • 코드 세그먼트 0x8( RPL:0 ) : 베이스 어드레스 : 0, 리미트 : 0xffff ffff, 즉 2GB 까지의 크기를 가지고 있다.
    • 데이터 세그먼트 0x23 : 어플리케이션에서 사용하였던 데이터 세그먼트가 그대로 사용되어 짐. 인텔 마이크로프로세서에서는 데이터 세그먼트가 현재의 실행 특권레벨 보다 낮은 것은 모든 허용하기 때문에 괜찮고, 윈도우에서 User 레벨에서 Kernel 레벨로의 진입 시 데이터 세그먼트에 대한 내용은 바꾸어 주지 않는다.
    • 스택 세그먼트 0x10 : 어플리케이션의 스택세그먼트와 비슷하며, DPL 값은 0 이다. ( 데이터 세그먼트와 달리 스택 세그먼트의 경우 현재 실행되고 있는 특권수준( CPL )과 같은 특권레벨( DPL )을 가져야 하기 때문이다.
    • FS 세그먼트 : 베이스 어드레스 0xffdf f000, 이 FS 세그먼트 레지스터의 베이스 어드레스는 쓰레드 마다 바뀌지 않는다. 커널레벨에서의 FS 세그먼트 레지스터는 유저 레벨에서 처럼 쓰레드 마다 독립적인 용도로 사용되어지지 않으며, 운영체제에서 현재 프로세서의 여러가지 정보를 나타내기 위하여 KPCR( Kernel's Processor Control Region ) 이라는 구조체를 만들어 사용하고 있다. 이 구조체의 내용은 IRQL 값이라든지, 프로세서의 개수, 각종 디스크립터 테이블의 위치 정보가 들어가 있게 된다.
    • 시스템 프로그래머 중 프로그래머가 직접 인터럽트를 핸들링함으로써 유저레벨로부터 커널레벨로 제어 이행이 수행될 경우 반드시 FS 레지스터를 커널레벨의 세그먼트 값 0x30 으로 바꿔줘야 한다. 만약 유저레벨에서 커널레벨로의 진입시 이 FS 의 내용을 커널레벨로 바꾸지 않는다면 PsGetCurrentProcess 함수는 유저레벨의 FS 베이스 주소로 액세스를 하여 잘못된 결과를 낳을 것이다.

 


'책 정리 > Windows 구조와 원리 그리고 Codes' 카테고리의 다른 글

11장. 페이지 관리  (0) 2009.11.15
10장. 페이징  (0) 2009.11.15
8장. 메모리 관리  (0) 2009.11.15
4장. 프로시저와 스택 구조  (0) 2009.11.15
3장. 기계어의 구성  (0) 2009.11.15

설정

트랙백

댓글