11장. 페이지 관리

 

  • 요구페이징( Demand Paging ) : 모든 내용을 메모리에 올려놓지 않고, 실행되어지는 프로세스에서 요구하는 시점에서 그 내용을 올리기 위한 페이지를 할당하는 기법

    1. 마이크로프로세서는 프로그램이 접근하고자 하는 메모리가 유효한지 알아보기 위해 그 페이지 테이블의 유효 비트를 살펴본다.
    2. 유효 비트가 0으로 세트되어 유효 하지 않다면 Page Fault Interrupt 를 발생 시킨다.
    3. OS는 메인메모리에서 빈 공간을 찾아본다. 빈공간이 없으면 페이지 교체 작업을 수행하여 빈 공간을 확보
    4. 새로 할당된 빈 공간에 해당 페이지의 내용을 디스크로 부터 읽어들인다.
    5. 요청한 페이지가 메모리에 있다는 사실을 마이크로프로세서가 인식할 수 있도록 페이지 테이블의 내용을 갱신
    6. 트랩에 의해 발생한 인터럽트를 빠져나감으로써 페이지 에러가 발생한 명령어가 다시 시작
  • Page Fault Exception Handler

    • 마이크로프로세서는 해당 프로세스의 커널 스택에 페이지 폴트의 원인에 대한 에러 코드와 기타 레지스터 정보를 Push 하여 넣고, CR2 레지스터에는 페이지 폴트가 발생한 주소를 세팅하여 놓은 후 페이지 부재 에러인 Int 14 를 발생시킨다.
    • Int14가 발생했을 당시의 스택 내용으로, 만약 커널레벨에서 실행되던 코드가 페이지 부재를 발생시켰을 경우에는 Privilege Level 변화가 없는 경우로 Page Fault 발생 당시의 레지스터 값과 에러가 발생한 이유를 설명하여 놓은 Error Code 값을 스택에 넣어주게 된다.
    • 유저 레벨에서 발생시켰을 경우에는, MicroProcessor는 실행 중이던 프로세스의 스택을 커널에 존재하는 스택으로 스위칭한 후 Previlege Level 변화가 없을 경우 들어갔던 내용에 유저레벨에서 실행되던 ESP와 SS 레지스터가 들어가게 된다.
    • Page Fault 는 참조하는 페이지가 메인 메모리에 존재하고 있지 않을 때, 접근 권한이 없는 프로세스가 해당 페이지를 접근하였을 때에도 발생하며 이러한 사항에 대해서는 Error Code 를 통해 알린다.
    • Error Code

      • P ( bit 0 ) : 0 - 참조하고자 하는 페이지가 유효하지 않을 상태로 페이지 테이블 또는 페이지 디렉토리의 P 비트가 0 이다.
      • 1 - 접근 권한에 대한 에러로( Read/Write ) 액세스 권한 또는 (User/Supervisor) 특권레벨 위반에 대한 페이지 폴트이다ㅣ.
      • R/W( bit 1 ) : 0 - 읽기 권한이 없는데 읽기를 시도하였다.
      • 1 - 쓰기 권한이 없는데 쓰기를 시도하였다.
      • U/S( bit 2 ) : 0 - 특권레벨 0, 1, 2( 커널레벨 )에서 페이지 폴트가 발생하였다.
      • 1 - 특권레벨 3( 유저레벨 ) 에서 페이지 폴트가 발생하였다.
    • 페이지 폴트가 발생한 주소에 대해서는 CR2 레지스터를 통해 알리게 된다.
  • 선페이징( Prepaging ) : 대부분의 프로그램이 참조한 근처의 메모리를 다시 참조한다는 지역성의 특성을 이용해 요구한 페이지 외에 그 근처의 페이지까지 함께 불러들이는 방식이다. 읽어들이고자 하는 내용이 코드 페이지인지 또는 데이터 페이지인지에 따라 읽어들여 놓는 크기가 달라지도록 하고 있다.
  • Page Out : 물리적 메모리에 있는 페이지의 내용에 대하여 하드디스크로 복사하여 놓는 작업
  • Page In : 하드디스크에 있는 페이지의 내용이 물리적 메모리로 옮겨와 사용되어지는 것
  • Paged Memory or Pageable Memory : 가상 메모리 공간 중에서 Page In과 Page Out 이 발생할 수 있는 가상 메모리 공간
  • NonPaged Memory : Page In 을 처리하기 위한 루틴이 포함되어 있는 Page Fault Handler 가 Page Out 되어 있다면 Page Fault 를 처리 할 수 없게 된다. 이러한 공간은 절대 Page Out 이 발생되지 않는 공간에 있게 된다. 이를 NonPaged Memory 라고 한다.
  • 페이지 교체 정책( Page Replacement Policy ) : 가장 좋은 교체 정책은 앞으로 가장 오랜 시간 동안 사용되지 않을 페이지를 찾아 교체하는 것이다.

    • FIFO( First In, First Out ) : 가장 먼저 들어온 페이지를 교체
    • LRU( Least Recently Used ) : 가장 오랫동안 사용되지 않은 페이지를 교체
    • Additional Reference Bits 알고리즘
    • Second Chance 알고리즘
  • 스레싱( Thrashing ) 현상

    • 어떤 프로세스가 너무 작은 양의 메모리 페이지 할당으로 실제 프로세스가 원하는 명령어의 실행 시간보다 페이지 부재의 발생으로 페이지 교체를 수행하는데 소비하는 시간이 더 많아 지면, 컴퓨터 성능에 심각한 성능 저하를 가져 올 것이다. 프로세스 수가 많아 질 수 록 CPU이용율은 점점 늘어나지만 일정 개수가 되고 나면 이용율이 급격히 떨어지게 된다. 이를 위해 각 프로세스가 가져야하는 페이지의 수를 적절히 조절해 주어야 할 것이다.
  • 작업세트 관리

    • 작업세트란? 하나의 프로세스에서 메인 메모리에 올라갈 수 있는 페이지들의 양
    • 고정 크기 할당 정책  : 프로세스가 생성되어질 때 메인 메모리에 유지할 페이지수를 결정하게 되며 그 이후 그 프로세스의 작업세트 크기를 계속 유지하게 된다. 추가적인 페이지가 필요할 때에는 페이지의 교체를 수행해야 한다.
    • 가변 크기 할당 정책 : 프로세스가 실행되는 동안 페이지의 할당 수를 다르게 하는 것, Page Fault 가 자주 발생하는 프로세스의 경우 그 페이지의 할당 수를 늘려주어 Page Fault 를 줄이고, Page Fault 가 적게 발생하는 프로세스의 경우 페이지 할당 수를 줄여주어 다른 프로세스가 사용할 수 있는 메인 메모리의 페이지 수를 늘려줄 수 있게 한다. 단, 이러한 모니터링에 의한 많은 오버헤드를 초례하게 된다.
    • 지역적 교체 정책 : Page Fault 를 일으킨 프로세스의 페이지에 대해 그 프로세스가 소유한 작업세트 내의 페이지로 교체 페이지를 선택
    • 전역적 교체 정책 : 전역 메인 메모리 중 커널이 위차한 페이지 or 락이 걸린 페이지를 제외한 모든 페이지를 교체 대상으로 삼는다.
    • Windows 에서는 작업세트의 상한치 하한치를 설정하여 놓은 후 그 프로세스가 가질 수 있는 작업세트의 크기를 이 범위 내에서 가질 수 있도록 보장해 주고 있다. 가용 페이지가 넉넉히 있는 상태에 Page Fault 발생시 작업세트의 상한치를 넘지 않는 범위 내에서 메인 메모리의 페이지를 작업세트로 할당, 상한치 까지 채워졌으면 지역적 교체 정책에 따라 LRU 의 교체정책에 의해 수행. 메인 메모리의 가용 메모리의 가용 메모리가 시스템이 정한 임계치 보다 낮을 경우에는 각 프로세스가 가지고 있는 작업세트를 조사하여 하한치보다 넘게 할당된 페이지들을 FIFO 알고리즘으로 회수하게 된다.
  • 페이징의 효과적 이용 방법
  1. typedef struct _ListEntry
  2. {
       int key;
  3. _ListEntry *pre, *next;
  4. DWORD flags;
  5. BYTE filename[1024];
  6. } ListEntry, *PListEntry;
  7. 2.
  8. typedef struct _DataBody
  9. {
        DWORD flags;
  10. BYTE filename[1024];
  11. } DataBody, *PDataBody;
  12. typedef struct _ListEntry
  13. {
  14. int key;

    _ListEntry *pre, *next;

  15. PDataBody data;
  16. } ListEntry, *PListEntry;

 

 위의 데이터구조는 하나의 데이터 구조에서 모든 엔트리를 다 가지고 있으며, 아래는 실제 데이터로 사용되는 부분과 검색에 의해 자주 참조되는 키를 분리하여 놓았다.

해당 데이터에 대하여 키에 대한 검색이 자주 일어나면 위쪽 데이터 구조에서는 메번 전체 키 검색을 위해 모든 데이터가 있는 자료구조 때문에 더 많은 페이지를 로드해야 하지만, 아래쪽 형태는 이를 분리하여 검색시 필요한 데이터 량을 줄여서 더 적은 페이지를 로드하게 해주어 페이지를 효과적으로 사용하게 해준다.


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

10장. 페이징  (0) 2009.11.15
9장. 세그먼테이션  (0) 2009.11.15
8장. 메모리 관리  (0) 2009.11.15
4장. 프로시저와 스택 구조  (0) 2009.11.15
3장. 기계어의 구성  (0) 2009.11.15

설정

트랙백

댓글

10장. 페이징

 

  • 하나의 프로세스에는 반드시 하나의 페이지 디렉토리가 존재 해야 한다.
  • 윈도우에서는 프로세스의 스위칭이 일어날 때마다 CR3 레지스터의 페이지 디렉토리 PFN 을 바꾸어줌으로써 해당 프로세스가 사용하는 가상 메모리를 전혀 다른 물리적 주소와 매핑시킬 수 있게 하는 것이다.
  • 4MB 단위의 페이징 시스템을 구성할 경우 물리적 메모리에 대한 할당의 최소 단위가 4MB이므로 엄청난 내부 단편화가 발생할 것이기 때문이다. 하지만 4MB단위의 페이징 시스템의 장점을 살리기 위해 128MB 이상의 물리적 메모리를 가진 시스템에 대해서는 0x8000 0000 ~ 0x9fff ffff 에 로드하게 하고 있으며, 이 영역에 대해서는 4MB 단위의 페이지로 구성하게 된다.
  • 윈도우에서는 0xc000 0000 ~ 0xc03f ffff 에 PTE, PDE 정보를 매핑하고 있다. 0x0~0xfff 의 PTE정보는 0xc000 0000에, 0x1000 ~ 0x2fff 주소의 PTE정보는 0xc000 0004 부분에 저장된다.

    • PTE 주소 = 0xc000 0000 + ( (가상주소 / 0x1000) * 4 )
    • PDE 주소 = 0xc030 0000 + ( (가상주소 / 0x400000 ) * 4 )
    • 가상주소 0x1000000 의 PTE 주소는 0xc000 0000 + ( (0x1000000/0x1000)*4 ) = 0xC000 4000
    • PDE 주소는 0xc000 0000 + ( (0x1000000/0x400000)*4 ) = 0xc0300010
  • 페이징에서의 특권 레벨

    • 유저 레벨 : 0x0 ~ 0x7fff ffff : 하위 2GB의 PDE, PTE의 User/Supervisor 비트는 1로 세팅
    • 커널 레벨 : 0x8000 0000 ~ 0xffff ffff : PDE, PTE 의 User/Supervisor 비트는 0 으로 세팅하고 있다.
  • System Page Table : 커널 영역의 메모리를 나타내는데 사용되는 페이지 테이블, 윈도우는 커널 메모리 영역을 공유하기 위해 하나의 시스템 페이지 테이블을 유지하고 있다.
  • 동일한 DLL 이 여러 프로세스에 공유되어 메모리의 절약을 한다. 윈도우에서는 DLL을 공유하기 위해서 Windows 로더가 DLL을 메모리에 적재할 때 Memory Mapped File 형태로 DLL 파일을 메모리에 매핑하고 있으며, 이는 마치 App 에서 프로세스간 공유 메모리 또는 파일을 메모리에 매핑하는 방식과 동일한 방법이다.
  • 동일한 DLL 공유시 한 프로세스가 일부 코드를 다른 DLL과 다르게 수정 할 경우에는 Copy-On-Write 라는 개념을 사용한다.

    • COW 는 공유 DLL 을 수정 해야 할 경우, 그 페이지를 새로운 페이지에 동일한 내용으로 복사하여 변경을 하고, 새롭게 변경된 페이지를 가리키도록 한다.
    • Windows는 DLL이 메모리에 올라갈 때에 모든 코드 페이지에 대해 읽기 전용 속성의 페이지로 만들게 되며, 사용자 또는 기타 시스템이 이 페이지의 내용을 수정하기 위해서는 VirtualProtect() or VirtualProtectEx() 의 Win32 API를 사용하여 읽기/쓰기 가 가능한 페이지 속성으로 변경하여 주어야 한다. 하지만 실제 PTE내용은 변경하지 않고 읽기 전용을 유지하고, Windows 내부에서 이 페이지의 내용이 읽기/쓰기가 가능한 COW 페이지임을 세팅하여 놓기만 한다. 그리고 이후 사용자가 이 페이지에 대하여 쓰기를 시도할 경우 마이크로프로세서는 메모리 접근 에러를 발생시키고, Windows 운영체제의 페이지 폴트 핸들러에서 이 페이지의 내용이 읽기/쓰기 가능한 Copy-On-Write 페이지임을 확인한 후 이전에 설명한 방법에 의하여 Copy-On-Write가 행해지게 된다.
  • PPTE( Prototype Page Table Entry )

    • Windows 는 공유된 DLL 또는 메모리 맵에 의하여 파일이 공유되어 질 때, PPTE라는 PTE를 하나 더 생성한다.
    • 새로운 프로세스에서 DLL 의 공유를 원하는 경우 PPTE정보를 참조하여 이 DLL의 PTE정보를 구성하게 된다.
    • 공유하고 있는 MemoryMapped File 또는 공유된 DLL 에 대하여 Windows 에서 본래의 페이지 위치를 이 별도의 PPTE를 통하여 관리( COW 에 의해 가리키는 페이지가 다른 곳으로 바뀔수 있는데, 이 경우 PPTE를 통해 본래의 PTE 정보를 찾아갈 수 있다 )
    • 공유된 페이지가 Invalidated or Page-Out 되어 졌을 때, 그 페이지를 공유하고 있는 모든 프로세스의 PTE에 대하여 PPTE를 지시 할 수 있는 특별한 형태의 데이터를 써 넣게 된다. 그리고 프로세스에서 그 페이지에 접근하려 할 경우 Page-In 이 되고, PPTE정보에 이 페이지가 로드된 물리적 어드레스로 갱신시켜주면 된다. 다른 프로세스에서 이 페이지 내용을 참조 할 경우 PTD 에 저장되어 있는 PPTE정보를 참조하여 Page-In 되어 있는 물리적 주소를 얻어 올 수 있게 되는 것이다.

 

  • 2.JPG 공유되고 있는 페이지에 대해 Process B 에 의해 먼저 접근이 이루어져 해당 페이지의 물리적 메모리를 읽어 들인다. 이때 PPTE 정보만이 실제 물리적 주소를 가리키도록 생신 시켜준다. 이후에 Process A 는 PPTE 정보를 통해 공유 페이지에 대한 물리 주소를 얻어 온다.

 

 

 

 

 

 

 

 

 

 

  • Windows 에서는 각 프로세스의 독립적인 메모리를 유지하기 위해 프로세스 마다 페이지 디렉토리를 가지고 있으며, 서로 다른 프로세스로의 전환 시에는 마이크로프로세서의 CR3 값을 전환하고자 하는 프로세스의 페이지 디렉토리로 변경함으로써 간단히 다른 프로세스의 메모리 영역으로 바꾸고 있다.

 

 


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

11장. 페이지 관리  (0) 2009.11.15
9장. 세그먼테이션  (0) 2009.11.15
8장. 메모리 관리  (0) 2009.11.15
4장. 프로시저와 스택 구조  (0) 2009.11.15
3장. 기계어의 구성  (0) 2009.11.15

설정

트랙백

댓글

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

설정

트랙백

댓글

8장. 메모리 관리

  • 페이지 교체 기법 : 요청된 모든 데이터가 실 메모리에 모두 매핑되어 있고, 다른 주소의 데이터를 프로그램에서 요청 할 경우, 현재 사용 중인 어떤 페이지를 새로 요청한 페이지로 교체해야 하는데 이를 페이지 교체 기법이라 한다.
  • 페이지 테이블을 1단계로 하게 되면, 각 프로세스가 4GB 까지 매핑 가능하다고 할 때, 각 엔트리는 프레임 번호를 가지고 있게 된다. 한 엔트리의 크기가 4Bytes가 될 것이고, 갯수는 1048576 개가 되므로, 총 4MB가 된다. 프로세서가 3개 수행되는 경우에는 12MB 가 필요하게 될 것이다. 프로세서 갯수에 따라 메모리 정보 표시를 위해 상당한 메모리가 요구된다. 그래서 이를 두 단계로 나누게 되면 프로세서 갯수에 상관없이 Page Directory(4KB), Page Tables(4MB) 가 필요하게 된다.
  • Page Directory 부분만 메모리에 올려놓고, Page Table 에 대해서는 필요 시에만 만들어 메모리에 올려 놓아서 이와 같은 낭비를 줄이고 있다.
  • 세그먼트 기법 : 프로그램과 관련된 데이터들에 대하여 여러 개의 세그먼트들로 나누어 다루게 되며 이 세그먼트의 크기는 똑같을 필요가 없다.
  • 응용 프로그램 수행시 세그먼트 형태로 코드부, 리소스부, 데이터부, 디버깅 정보, 스택 메모리 등의 부분을 따로 만들어 배치 하게 된다. 각 세그먼트의 세부 사항은 인텔 매뉴얼을 참고 하기 바란다. 마이크로프로세서는 세그먼트 테이블을 참조하여 해당 세그먼트의 시작 주소와 더해져 실제적인 물리적 위치로 변환해 주기 때문에 다른 세그먼트의 데이터를 다루기 편리하다.

    1.JPG 

 

  •  이러한 세그먼트 기법은 문제점이 있는데, 세그먼트 크기가 크고, 메모리가 모든 세그먼트를 올리기에 불충분 하게 되면, 세그먼트 들을 올리고 내리는 작업을 반복해야 되고, 크기가 커서 큰 오베헤드를 지불해야한다. 해결방법으로, 세그먼트의 크기를 가능한 작게 만들어 배치하는 것인데 즉, 세그먼트와 페이징 기법을 병합하여 사용하는 것이다.
  • 페이징은 외부 단편화가 존재하지 않고 주기억장치를 효율적으로 사용할 수 있으며, 세그먼트의 경우 가변적인 자료구조, 모듈성의 처리, 그리고 공유와 보호를 지원하는 등의 장점을 가제 된다.

설정

트랙백

댓글

4장. 프로시저와 스택 구조

 

  • 함수가 호출 될 때 스택의 변화

    • 함수가 호출 되기 직전에 함수의 인자 값을 먼저 스택에 쌓고, 함수의 복귀 주소이전의 EBP 를 push, ESP를 이동 시킨다. 그리고 그 함수 스코프 내에 있는 지역 변수( 먼저 선언 한 것이 먼저 스택에 쌓인다 )를 push 한다.
    • 함수의 인자 값 : 제일 뒤에 있는 인자 값이 스택에 먼저 PUSH 된다.(default 로... 컴파일 옵션에 따라 달라 질 수 있다.)
    • 인자 값 접근 : EBP를 기준[복귀주소]으로 + 0x4[첫 번째 지역변수] or 0x8[두 번째 지역변수]... ( 32 비트 환경 )

      • ESP를 return 되는 함수 복귀 주소 가 저장 되어 있는 곳 이전 데이터를 가리키고 있다.

      함수가 return 될 때 스택의 변화

    • 지역변수 접근EBP - 0x4[ 이전의 EBP ], EBP - 0x8[ 지역변수1 ]

 

  • 스택에서 ESP의 위치만 바꿀 뿐, 기존에 있는 데이터는 쓰래기 값 처럼 대우를 한다. 데이터를 PUSH 할 때는 그냥 덮어서 쓴다.

 

  • 스택 프레임

    • 스택 프레임은 스택에서 PUSH 로 인한 ESP 의 변화로 인한 지역변수 접근 문제 때문에 만들어졌다. 이 때 EBP가 등장.

 

  • 파라미터 전달의 방법 : Calling Convention - 스택에 파라미터를 어떤 순서로 넣을지, 전달되어진 파라미터를 어느 곳에서 해제할 건인지 방식을 정하는 것

    • 이러한 Calling Convention은 컴파일러에 의해 코드가 자동으로 만들어 진다.
    •  __cdecl :  C/C++ 에서 default 로 사용하는 콜링 컨벤션 방식     ex ) int sum( int a, int b )

      • 파라미터 전달 : 오른쪽에서 왼쪽으로
      • 파라미터 해제 : 프로시저를 호출한 쪽에서 해제
    • __stdcall : Windows API 의 프로시저에서 사용하는 콜링 컨벤션 방식   ex ) int __stdcall sum( int a, int b )

      • 파라미터 전달 : __cdecl 과 같음
      • 파라미터 해제 : 프로시저가 복귀되기 전에 이루어진다.
      • 장점

        • 함수의 독립성이 뛰어나다 : 함수가 리턴되어진 후에 그 프로시저의 SP가 이전 상태로 복원되어 있어서, 복귀후에 호출 프로시저에 대하여 더 이상 신경 안써도 된다.
        • 스택 해제 코드가 호출한 프로시저 안에 있어서, 프로시저가 여러 곳에서 호출 되더라도 스택을 해제하는 코든느 프로시저 내에 하나만 존재하여 __cdecl 방식보다 코드크기가 줄어 든다.
    • __fastcall

      • 파라미터 전달 : 처음 두 개까지의 파라미터는 스택을 사용하지 않고, ecx, edx 레지스터를 사용하고 그 이상의 파라미터에 대해서만 오른쪽에서 왼쪽 방향으로 스택에 저장
      • 스택 제거는 __stdcall과 동일
  • 리턴 값 전달 방법

    • 32비트 보다 작거나 같은 값 일 경우 : 프로시저 리턴 전에 EAX에 리턴 값을 저장
    • 32비트 보다 큰 경우 : 낮은 주소 영역의 32비트 -> EAX , 상위 32비트 -> EDX 에 저장

 

  • Naked Function

    • Interrupt Handler 나 Hooking 루틴을 만들다 보면 프로그래머가 직접 스택 프레임을 구성하고, 원하는 형태로 함수의 구조를 만들어야 하는 경우 사용을 한다.
    • 모든 스택 프레임에 대한 구성과 해제를 프로그래ㄴ머가 직접 신경 써 줘야 한다.
    1. __declspec(naked)NamedFunc()
      {
    2. int i;  int j;
    3. __asm {
    4. push ebp
    5. mov ebp, esp
    6. sub esp, __LOCAL_SIZE }
    7. i = 1; j = 2;
    8. __asm {
    9. mov esp, ebp
    10. pop ebp
    11. ret }
    12. }

 

  • Windows 에서의 스택 구조

    • 쓰레드 생성 시 디폴트로 1MByte의 메모리를 예약하여 놓고 이 중 1개의 페이지인 4byte 만을 실제 메모리와 매핑, 다른 1개는 가드 페이지( Guard Page ) 형태로 만들어 놓는다. 나머지 메모리 들에 대해서는 예약만 해 놓고 실제 메모리와 매핑은 시켜놓지 않은 상태로 둔다.
    • 가드 페이지로 페이지 보호를 수행 한다. 최초 4Kbyte의 스택을 초과 하여 사용할 시에 가드 페이지 영역을 새로운 Committed Page로 바꿔주고 그 아래 페이지 영역의 부분을 새로운 가드 페이지로 바꾸어 준다.
    • 이런식으로 계속 페이지를 Committed Page로 바꾸지만, 마지막 페이지 직전까지 할당 했을때, 마지막 페이지는 Guard Page로 바꾸지 않고 Reserved Page로 그냥 둔다. 왜냐하면, 전체 영역에 대해 Commit 되게 하면, 쓰레드가 자신의 스택 영역을 초과하여 사용하더라도 이를 알아차리지 못하기 때문에, 다른 데이터 영역을 손상 시키고, 스택에 대한 오버플로우 문제를 발생 시킬수 있기 때문이다.
    • 나머지 페이지는 예약만 해놓아서 이 프로세스 공간에 대한 메모리 할당을 스택 용도 이외로 사용하지 못하게 한다. ???

 

 

 

설정

트랙백

댓글

3장. 기계어의 구성

  • 프로그램을 작성하고, 컴파일하면 실행파일로 만들어지고 이는 단순한 숫자 형태로 만들어진다. 이런 실행파일이나 이미 실행되어 메모리에 올라와 있는 실행 이미지를 분석하고자 할 때에는 이 숫자를 사람이 보다 이해하기 쉬운 형태인 어셈블리 언어 형태로 바꿔 볼때 사용하는 것이 디버거 또는 디스어셈블러 등이다.

 

  • 기계어 형식 => OP Code, Operand #1, Operand #2 ( Operand 수는 가변적 based on OP Code / operand #2 -> operand #1 으로 주로 조작이 이루어 진다. )

 

  • 명령어 표 보는 법 : m : Memory, r : Register

    • Imm8 : 8Bit - 1Byte
    • Imm16 : 16Bit - 2Byte
    • Imm32 : 32Bit - 4Byte
    • r/m32 : 범용 레지스터 또는 4Byte의 메모리
    • rel8 : 1Byte 사이즈 범위 내의 상대주소

      • JMP rel8 : 1Byte 사이즈 범위 내의 상대주소로 점프
      • CLL rel16 : 16비트 코드 실행 시에 2Byte의 사이즈 범위 내의 상대 주소로 함수 호출

 

  • 번지 지정 방식

    • 이미디어트( Immediate ) 번지 지정 방식

      • MOV EAX, 0x12345678 : EAX에 78 56 34 12 상수 값이 저장, 상수 값을 오퍼랜드로 사용
    • 레지스터 번지 지정 방식

      • MOV EAX, EBX

    • 직접 번지 지정 방식

      • MOV EAX, [0x12345678] : 0x12345678 에 있는 메모리 내용을 4bytes 읽어서 EAX에 저장
    • 레지스터 간접 번지 지정 방식

      • MOV EAX, [EBX] : EBX에 저장된 메모리 주소로 이동해서 메모리 내용을 4bytes 읽어서 EAX에 저장
    • 베이스 레지스터와 변위가 있는 레지스터 간접 번지 지정 방식

      • MOV EAX, [EBX + 0x4 ] : EBX가 base address로 하여 1 바이트 값을 취한다
    • 베이스 레지스터와 인덱스가 있는 레지스터 간접 전지 지정 방식

      • MOV EAX, [EBX + ECX * 2 ] : EBX - base address, BCX - index reg, 스케일 값 - 2
    • 베이스 레지스터와 인데스 그리고 변위가 있는 레지스터 간접 번지 지정 방식

      • MOV EAX, [EBX + ECX * 2 + 0x1234] : EBX - base address, BCX - index reg, 스케일 값 - 2

 


설정

트랙백

댓글

2장. 데이터의 표현과 메모리 구조

 

  • 8비트 데이터 버스에서 한번 접근시 1바이트를 읽어 오는데, 이는 하나의 메모리 안에 8개의 병렬로 메모리 가 존재하여, 행,열 주소 데이터를 가지고 8개의 메모리에 접근하여 데이터를 가져온다.
  • 8086의 16비트 프로세서에서 메모리 칩과 프로세서와의 관계에서, 메모리 접근시에는 두개의 메모리 칩이 필요하다.

    • 짝수 바이트를 저장는 D0 ~ D7, 홀수 바이트를 저장하는 D8 ~ D15가 있다. 짝수 번지에 워드 크기 단위로 접근시에는 한 번의 데이터 전송으로 끝날 수 있지만 짝수 번지에 워드 크기 단위로 접근을 하면, 두번의 접근이 필요하다.
  • 32( 4개의 메모리 칩이 필요 ), 64비트에서의 메모리 접근도 이를 통해 유추 할 수 있을 것이다.

 

 

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

9장. 세그먼테이션  (0) 2009.11.15
8장. 메모리 관리  (0) 2009.11.15
4장. 프로시저와 스택 구조  (0) 2009.11.15
3장. 기계어의 구성  (0) 2009.11.15
1장. 컴퓨터의 구조와 역사  (0) 2009.11.15

설정

트랙백

댓글

1장. 컴퓨터의 구조와 역사

 

  • 16비트 마이크로 프로세서

16비트 데이터 버스를 의미하는 것이며, 데이터 전송을 위해 핀을 16개 사용한다는 뜻이다.

  • 8086

    • 16비트 CPU로서, 16비트 데이터 버스를 가지고 있지만 더 많은 메모리 엑세스를 위해 20비트 어드레스 버스를 가진다.
    •  세그먼트 방식 도입 : 내부 레지스터는 모두 16비트의 크기를 가지므로 20비트의 크기(1MB 주소 사용 가능)를 그대로 사용은 할 수가 없어서...

      segment(16-bit):offset(16-bit) -> 실제 주소사용시 16비트의 세그먼트값을 4비트 좌로 쉬프트하고 이를 offset과 더한다.
      ex : 0xb1234 = b123h(segment) + 4(offset) 하지만, 한 물리 주소를 위한 여러 개의 segment:offset 쌍이 존재

       

      IP(Instruction Registe) : 실행될 명령어를 저장
      PC(Program Counter) : 다음에 실행될 명령어를 가져올 메모리 주소를 저장

  • 80836

    • 32비트 프로세서. 시스템, 제어, 디버그 레지스터의 추가
    • 시스템 레지스터( System Register )

      • 보호모드에서의 프로세서 제어와 검사를 위한 목적
    • 제어 레지스터(Control Register )

      • CR0, CR2, CR3
    • 디버그 레지스터

      • 하드웨어 브레이크 포인터를 가능하게 하는 레지스터( 4개 까지 가능 )
      • 해당 메모리 주소가 프로그램에 의해 액세스 되었을 때 프로그램이 멈추어 디버깅 루틴으로 제어가 
        넘어 갈 있도록 해준다.
    • TLB( Translation Lookaside Buffer ) 와 Test 레지스터

      • 일정 개수 만큼의 변환 내용( 가상 메모리 - 실 메모리 주소 ) 을 이 버퍼에 보관하여 변환 시간을 줄여 줌
      • 80386 이후의 마이크로프로세서는 이 TLB 내용에 대해 사용자가 직접 그 내용을 보거나 조작 가능, 이는 테스트 레지스터( Test Register )인 TR6, TR7에 의해 이루어진다.
    • TLB 제어

      • 읽기 요청

        1. 검색하고자 하는 선형 주소 값을 TR6( bit 12 ~ 31 ) 에 쓰기
        2. TR6의 C bit 를 1로 Set

        3. TR6의 M( bit4 )  가 0 이면 검색 성공( TR6, TR7에 주소가 저장 된다 ), 1이면 실패.
      • 쓰기 요청

        1. TR6, TR7에 쓰고자 하는 정보를 쓰고, T6레지스터의 C( bit 0 ) 을 0 으로 clear

 

  • 80486 에서는 캐쉬 데이터를 사용자가 직접 제어 할 수 있도록 추가된 레지스터

    • TR3( cache data register )

      • 캐쉬에 데이터를 쓰거나 읽을 때 캐쉬 한 라인에 포함 되어 있는 16byte의 데이터에 대한 창 역할
    • TR4( cache status test register )

      •  캐쉬 쓰기 또는 읽기 작업
    • TR5( cache control test )

      • 캐쉬의 세트와 라인을 선택, 캐쉬 제어

 

 

 

 

 

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

설정

트랙백

댓글