페이지 테이블 공간 문제를 해결하기 위해 다양한 방법들이 제안되었습니다만, 가장 많이 사용되는 것이 다단계 페이징 기법입니다.
여기에서는 2단계 페이지 테이블 구조를 설명드리겠습니다.
그림의 가장 오른쪽에 메모리가 있고, 가운데에 페이지 테이블이 존재합니다.
이 기법의 핵심은, 페이지 테이블도 메모리에 적재되므로 페이지 테이블 자체를 페이징한다는 것입니다.
즉, 페이지 테이블 전체는 디스크에 저장해두고, 필요할 경우 하나씩 적재하는 방법이지요.
따라서, 페이지 테이블을 구성하는 각 페이지가 디스크 혹은 메모리에 있을 수 있으므로, 이러한 정보를 담고 있는 상위 레벨의 페이지 테이블이 하나 더 필요합니다.
물론 상위 레벨의 페이지 테이블은 항상 메모리에 있어야겠지요.
여기에서는 각각을 구분하기 위해 기존의 페이지 테이블을 내부 페이지 테이블(inner page table), 상위 레벨의 페이지 테이블을 외부 페이지 테이블(outer page table)이라 부르겠습니다.
2단계 페이지 테이블 체계를 사용한 주소 변환
논리 주소(4K 페이지 크기의 32비트 주소)가 분할됩니다.
20비트 페이지 번호입니다.
12비트 페이지 오프셋입니다.
페이지 테이블 자체가 호출되기 때문에 페이지 번호가 더 분할됩니다.
외부 페이지 테이블의 인덱스는 10비트입니다.
내부 페이지 테이블의 인덱스는 10비트입니다.
3단계 페이지 테이블
64비트 프로세서의 3단계 페이징
Hashed Page Table
논리 페이지 번호(logical page number)가 테이블에 해시된다
즉, Hash Table을 사용하여 논리 페이지 번호를 해싱한다.
해시 테이블은 동일한 위치에 해시된 요소들의 체인을 포함한다
논리 페이지 번호는 체인 내 항목(엔트리)들의 첫 번째 필드와 일치하는지 비교한다
만약 일치하는 항목이 발견된다면, 해당 물리 프레임 번호(physical frame number)를 얻는다
(논리 번호를 해시함수에 넣어 얻는 해시 값을 인덱스로 하여 일치하는 페이지 테이블 엔트리를 찾는다)
Inverted Page Table(역 페이지 테이블)
페이지 테이블의 공간 오버헤드
페이지 테이블 크기는 프로그램 크기에 비례합니다.
각 페이지(4KB)마다 하나의 페이지 테이블 엔트리(4B)가 필요합니다.
실제로는 한 번에 일부 페이지만 필요합니다.
역 페이지 테이블 (Inverted Page Table)
앞에서 봤던 페이징 구조에서는, 논리 주소를 물리 주소에 매핑하는 정보를 담는 페이지 테이블을 이용했다. 이 페이지 테이블은 현재 페이지(page number)가 어떤 프레임(base address)에 저장되있는지를 나타내고 있었다. 즉 page number를 base address로.
하지만 Inverted Page Table에서는 페이지 프레임을 기준으로 매핑 정보를 페이지 테이블에 저장한다. 각각의 프레임들이 어떤 프로세스의 어떤 페이지에 할당되어 있는가를 나타낸다. 따라서 프레임의 수와 페이지 테이블의 엔트리 수가 같다. 페이지 테이블의 i번째 엔트리는 physical memory의 i번째 프레임에 해당한다.
CPU가 pid와 page number를 알려주면, 몇 번째 프레임에 해당하는 지 알려주는 구조이다.
각 페이지 프레임마다 하나의 페이지 테이블 엔트리.
각 페이지 테이블 엔트리는 프로세스 ID를 포함해야 합니다.
시스템에는 하나의 페이지 테이블만 있으면 충분합니다.
엔트리는 페이지 프레임의 수만큼 필요합니다.
이는 연관 검색(associative search)이며, 전체 테이블을 검색해야 합니다.
페이지 테이블을 저장하는 데 필요한 메모리를 줄이지만, 테이블 검색에 필요한 시간이 증가합니다.
따라서 해시 테이블이나 연관 레지스터를 사용해야 합니다.
Inverted Page Table Diagram
역 페이지 테이블 구조도
(참고)
CPU에서 논리 주소(logical address)를 생성합니다.
논리 주소는 PID, 페이지 번호(p), 변위(d)로 구성됩니다.
페이지 테이블을 검색하여 일치하는 항목을 찾습니다.
페이지 테이블 항목은 프로세스 ID(pid)와 페이지 번호(p)를 포함합니다.
물리적 주소(physical address)는 프레임 번호(i)와 변위(d)로 구성됩니다.
물리적 주소를 사용하여 실제 메모리에 접근합니다.
Segmentation
페이징 기법에서는 프로그램 이미지를 무조건 페이지라고 하는 고정된 크기로 잘라 메모리에 적재하였습니다.
이와는 달리, 프로그램 이미지를 세그먼트 단위로 적재하는 기법이 있는데, 이를 세그먼테이션이라고 합니다.
여기서 세그먼트란 프로그램 이미지를 구성하는 코드, 데이터, 스택, 힙, 심볼 테이블 등을 의미합니다.
즉, 프로그램을 단순히 바이트들의 배열로 보는 것이 아니라, 세그먼트들의 집합으로 이해하고, 이러한 단위로 메모리를 관리하자는 개념입니다.
세그멘테이션 (Segmentation)
프로그램은 여러 세그먼트의 집합입니다.
(데이터, 힙, 스택, 코드 등 다양한 세그먼트로 구성됩니다.)
(각 세그먼트는 물리 메모리에 개별적으로 배치됩니다.)
Segment Table
세그먼트 테이블
세그먼트 테이블은 프로그램 이미지 내에서 각 세그먼트의 위치를 나타냅니다.
예: 세그먼트 0, 세그먼트 1, 세그먼트 2, 세그먼트 3, 세그먼트 4.
논리 주소 구성 (Logical address consists of)
논리 주소는 <세그먼트 번호, 오프셋>으로 구성됩니다.
세그먼트 테이블
각 테이블 엔트리는 다음을 포함합니다.
base: 세그먼트가 메모리에 위치한 시작 물리 주소.
limit: 세그먼트의 길이.
세그먼트 테이블 베이스 레지스터 (Segment-table base register, STBR)
메모리 내 세그먼트 테이블의 위치를 가리킵니다.
세그먼트 테이블 길이 레지스터 (Segment-table length register, STLR)
프로그램에서 사용되는 세그먼트의 수를 나타냅니다.
세그먼트 번호 s는 s < STLR일 때 합법적입니다.
Address Translation with Segmentation Architecture
세그먼테이션 아키텍처를 사용한 주소 변환
세그먼트 테이블을 이용한 주소 변환 과정을 그림을 통해 설명드리겠습니다.
CPU가 요청한 논리주소 중 s로 표시된 상위 비트들은 세그먼트 테이블에서 인덱스로 사용되어, base 값을 통해 해당 세그먼트가 적재된 메모리의 시작주소를 알아냅니다.
논리주소 중 d로 표시된 하위 비트들은 limit 값을 통해 요청 주소가 해당 세그먼트의 범위를 넘지 않았는지 확인하고, 넘지 않았을 경우에는 base 값에 더해져서 물리주소로 변환됩니다. (위에서 봤던 limit register가 하는 역할과 비슷)
참고) 그림 설명
CPU는 논리 주소를 생성합니다.
논리 주소는 세그먼트 번호(s)와 변위(오프셋)(d)로 구성됩니다.
세그먼트 테이블에서 세그먼트 번호(s)를 사용하여 베이스(base)와 리미트(limit)를 검색합니다.
변위(d)가 리미트(limit)보다 작으면 물리 주소가 계산됩니다.
베이스(base)와 변위(d)를 더하여 물리 주소를 생성합니다.
변위(d)가 리미트(limit)를 초과하면 주소 오류가 발생합니다.
Segmentation
보호 (Protection)
보호 비트(Protection bits)는 세그먼트와 연관됩니다.
유효성 비트(validation bit).
읽기/쓰기/실행 권한.
코드 공유 (Code sharing)
코드 공유는 세그먼트 단위에서 발생합니다.
세그먼트 길이가 다양하므로
동적 저장 할당 문제(dynamic storage-allocation problem)가 존재합니다.
첫 맞춤(first-fit), 최적 맞춤(best-fit), 최악 맞춤(worst-fit)을 기억하시나요?
Segmentation에서 "보호 비트를 사용할 수 있고, 코드 공유를 할 수 있고, 동적 저장 할당 문제가 존재한다" 정도 알고 넘어가자