페이지 테이블 예제

가상 주소를 실제 주소로 변환해야 하는 경우 TLB가 먼저 검색됩니다. 일치하는 검색(TLB 적중)이 발견되면 실제 주소가 반환되고 메모리 액세스가 계속될 수 있습니다. 그러나 일치하는 일치하지 않는 경우(TLB miss라고 함), 메모리 관리 장치 또는 운영 체제 TLB 미스 처리기는 일반적으로 페이지 테이블의 주소 매핑을 조회하여 매핑이 존재하는지 여부를 확인합니다(페이지 워크). 하나가 있는 경우 TLB에 다시 기록됩니다(하드웨어가 가상 메모리 시스템의 TLB를 통해 메모리에 액세스하므로 이 작업을 수행해야 함) 오류 명령이 다시 시작됩니다(병렬로 발생할 수도 있음). 이 후속 번역은 TLB 히트를 발견하고 메모리 액세스가 계속됩니다. 주소를 번역하기 위해 CPU는 CR3 레지스터에서 P4 주소를 읽습니다. 그런 다음 인덱스를 사용하여 테이블을 걷습니다: 이제 한 조각만 누락되었습니다: 자체 테이블을 다시 가리키는 특별한 P4 항목이 필요합니다. 이렇게 하면 P4 테이블이 두 번 사용되는 가상 주소를 생성할 수 있습니다(P4로 한 번, P3으로 한 번). 재귀 매핑을 사용하면 고유한 가상 주소를 통해 각 페이지 테이블에 액세스할 수 있습니다. 수학도 체크 아웃: 모든 페이지 테이블이 사용 되는 경우, 1 P4 테이블, 511 P3 테이블 (마지막 항목은 재귀 매핑에 사용), 511*512 P2 테이블, 그리고 511*512*512 P12 P1 테이블. 따라서 134217728 페이지 테이블이 있습니다. 각 페이지 테이블은 4KiB를 차지하므로 저장할 134217728 * 4KiB = 512GiB가 필요합니다.

페이지당 4KiB * 512 P1 항목 * 512 P2 항목 * 512 P3 항목 = 512GiB 이후 하나의 P4 항목을 통해 액세스할 수 있는 메모리양입니다. 마지막 항목이 해제되면 P1, P2 또는 P3 테이블을 해제할 수도 있습니다. 그러나 모든 언맵에서 전체 테이블을 확인하는 것은 매우 비쌉입니다. 그래서 우리는 좋은 해결책을 찾을 때까지 TODO를 제자리에 둡니다. 나는 🙂 제안에 열려 있습니다. virtual->물리적 주소 계산은 4단계의 페이지 테이블을 예상하는 하드웨어에서 수행됩니다. P1 테이블의 항목에 액세스하려면 한 수준의 번역을 제거해야 합니다. 트릭은 모든 페이지 테이블이 테이블 수준과 무관하여 거의 동일한 형식을 가지고 있다는 것입니다. 따라서 CPU는 P4와 P3 테이블과 같은 차이를 보이지 않습니다. 페이지 테이블은 가상 주소와 실제 주소 간의 매핑을 저장하기 위해 컴퓨터 운영 체제의 가상 메모리 시스템에서 사용하는 데이터 구조입니다.

가상 주소는 액세스 프로세스에서 실행되는 프로그램에서 사용되며 물리적 주소는 하드웨어에서 또는 더 구체적으로 RAM 하위 시스템에서 사용됩니다. 페이지 테이블은 메모리의 데이터에 액세스하는 데 필요한 가상 주소 변환의 핵심 구성 요소입니다. 페이지 테이블에는 각 페이지 테이블 항목에 프레임 번호와 선택적 상태(예: 보호) 비트가 저장되는 페이지 테이블 항목이 있습니다. 가상 메모리 시스템에 사용되는 많은 상태 비트입니다. PTE에서 가장 중요한 것은 프레임 번호입니다. 글쎄, 그들은 다음 테이블의 주소를 계산하고 (존재하지 않는) 페이지 테이블로 처리합니다. 잘못된 주소를 생성하거나(XXX < 400)1인 경우 매핑된 페이지 자체에 액세스합니다. 이렇게하면 메모리가 쉽게 손상되거나 실수로 CPU 예외가 발생할 수 있습니다. 따라서 이 두 함수는 Rust 측면에서 안전하지 않습니다.

따라서 우리는 우리가 몇 가지 영리한 해결책을 찾지 않는 한 그들에게 안전하지 않은 기능을 만들어야합니다. 안전하지 않은 블록을 사용하여 원시 P4 포인터를 참조로 변환합니다. 그런 다음 옵션::and_then 함수를 사용하여 네 개의 테이블 수준을 통과합니다.