저번에 정리하던 거 이어서 하겠다
페이지 테이블의 한계 보완위해 각 페이지에 추가 데이터 제공한다
이를 보조 페이지 테이블(SPT)이라 부른다
이것도 페이지 테이블로 부르지만 헷갈리니 보조 붙여주자
SPT는 두 가지 목적에 쓰인다
페이지 폴트 발생 시
프로세스 종료 시
마음대로 만들면 되고 최소 두 가지 접근이 있다
세그먼트 기반
연속 페이지 묶음 단위로 관리
페이지 기반
개별 페이지 단위로 관리
추가로, 원한다면 페이지 테이블 자체를 SPT 추적에 활용할 수도 있다고 한다
이를 위해서는 threads/mmu.c
의 Pintos 페이지 테이블 구현 수정해야해서
고급 학습자에게만 권장한단다
할 건 아니지만 무슨 말인지 궁금하니 가볍게 뭔말인지만 알아보면
따로 보조 자료구조를 두는 대신 기존의 페이지 테이블 엔트리(PTE) 안에 SPT의 메타데이터를 넣는 방식이라고 한다
즉, 페이지테이블에 SPT도 같이 쓰는 방식이다
어떻게 하는지까지는…
나중에 다뤄보겠다
페이지 폴트 버그처리는 프로젝트 2까지만이다
프로젝트 3부터는 파일/스왑에서 페이지를 가져와야 함이라는 뜻일 수도 있다
그렇기에 userprog/exception.c
의 page_fault()
가 호출하는 vm_try_handle_fault()
(in vm/vm.c
) 를 구현해야 한다
수행해야하는 목록 ↓
SPT에서 폴트가 난 가상 페이지를 조회
유효한 접근 일 시에 해당 페이지 데이터가 파일 시스템, 스왑 슬롯, 제로 페이지인지 판단
공유(CoW 등)를 구현했다면, 프레임에 있어도 PTE가 안 잡혀 있을 수 있음
SPT가 이상한 곳(커널 가상 메모리 범위, 읽기 전용 페이지에 쓰기)에 오면 무효 처리하고 프로세스 종료 후 자원해제
프레임 확보
데이터를 프레임으로
파일 시스템/스왑에서 읽거나, 제로로 채우는 등
공유 구현해서 프레임에서 가져온거라면 추가 작업 불필요할 수 있다
해당 가상 주소의 PTE를 프레임으로 매핑
threads/mmu.c
의 함수 사용프레임 테이블은 각 물리 프레임에 대해 하나의 엔트리를 가진다
각 엔트리에는 현재 그 프레임을 차지하는 페이지의 포인터(있다면) 및 선택한 부가 데이터가 포함되어 있다
프레임 테이블은 eviction 정책 구현에 사용된다 (사용 가능한 프레임이 없을 때 축출 대상 페이지를 고르는 등)
사용자 페이지에 쓰일 프레임은 반드시 "user pool"
에서 palloc_get_page(PAL_USER)
로 얻어야 한다
이렇게 안얻으면 "kernel pool"
에서 할당되어 테스트 케이스 실패 할 수 있다
가장 중요한 연산은 미사용 프레임 확보다
여유 프레임이 있으면 쉽지만, 없다면 축출(evict) 로 프레임을 비워야 한다
축출 시 스왑 슬롯 할당 없이는 축출할 수 있는 프레임이 하나도 없고, 스왑도 가득 찼다면 커널 패닉 일으키면 된다
축출 과정 ↓
페이지 교체 알고리즘으로 축출할 프레임 선택
해당 프레임을 참조하는 모든 페이지 테이블의 참조 제거
필요 시, 페이지를 파일 시스템이나 스왑에 기록
페이지 교체 알고리즘 구현 위한 각 PTE의 두 비트다
accessed 비트: 페이지에 읽기/쓰기가 발생하면 CPU가 1로 설정
dirty 비트: 페이지에 쓰기가 발생하면 CPU가 1로 설정
이는 OS가 필요에 따라 0으로 재설정한다
무슨 alias 문제를 조심하란다
서로 다른 가상주소가 같은 물리 프레임 가리키는 상황을 의미한다
A/D 비트(Accessed/Dirty)는 접근에 사용된 그 PTE에만 반영되는데 그로 인해
동일 프레임이라도 어느 PTE를 통해 접근했느냐에 따라 A/D 비트가 불일치 할 수 있다
Pintos에서는 모든 사용자 가상 페이지가 해당 커널 가상 페이지와 에일리어스라서 이를 잘 처리해줘야 한다
방법은 여럿 있을거다
예를 들어, 두 주소의 accessed/dirty 비트를 모두 확인/업데이트하거나, 커널이 사용자 데이터를 접근할 때는 사용자 가상 주소만 사용하도록 하거나 하여 말이다
그 외 에일리어스는 공유 구현 또는 버그가 있는 경우에만 발생해야 한다
자세한 함수는…
여기서 참고 해라
다음인 스왑 테이블 관리는 내일 하겠다 ㅂ2