핀토스 프로젝트 3의 모든 테스트 케이스를 통과하지 못했지만
특히 swap에서는 swap-iter, swap-fork를 아직 통과 못했다.
그래도 글로 정리를 해야 내 것이 된다고 생각해서 Swap in/out에 대해서 정리해본다.
참고로 swap-iter 테스트 케이스는 M1인 경우 통과가 되지 않는데 같은 코드를 윈도우로 돌렸을 때 통과되는 경우가 있는듯했다.
스와핑은 물리적 메모리가 부족할 때 사용되지 않는 메모리 페이지를 디스크의 swap 영역으로 swap out시키고, 필요할 때 다시 swap in하여 메모리로 불러오는 기법이다.
-> 물리적 메모리를 효율적으로 사용할 수 있게 된다.
swap table을 어떤 자료구조로 구현하면 좋을까.
스왑 테이블이란 swap disk에서 사용 가능한 영역과 사용 중인 영역을 관리하기 위한 자료 구조이다.
비트맵을 사용하면 메모리 사용량을 최소화하고 페이지의 상태를 훨씬 빠르게 관리할 수 있다.
swap table을 비트맵으로 구현할 때의 장/단점?
- linked list: 각 노드가 추가적인 포인터를 필요로 하고, 특정 페이지를 찾으려면 순차적으로 탐색해야 한다.
- hash table: 매우 빠른 삽입, 삭제, 조회가 가능하다. 해시 충돌을 처리해야 하고 메모리 오버헤드가 크다.
- 비트맵 : 각 페이지를 1비트로 표현해서 매우 적은 메모리를 사용한다. 특정 페이지의 상태를 조회, 변경할 때 비트 연산을 해서 매우 빠르게 처리할 수 있다.
그러나 비트맵의 크기가 고정되어 있어서 스왑 공간의 크기가 변동될 경우 유연한 대처가 어려울 수 있다.
static struct bitmap *swap_bitmap;
const size_t SECTORS_PER_PAGE = PGSIZE / DISK_SECTOR_SIZE; /*한 페이지가 몇개의 섹터로 구성되는지*/
page
:페이지의 크기는 4KB(4096 byte)DISK_SECTOR_SIZE
: 디스크는 데이터를 물리적으로 저장하기 위해 섹터라는 단위로 나눈다. 디스크 섹터의 크기는 512 byte따라서 SECTORS_PER_PAGE
는 한 페이지가 몇 개의 디스크 섹터로 구성되는지를 나타낸다.
현재 핀토스에서 한 페이지는 8개의 디스크 섹터로 구성된다.
page 타입에 따라 anon_swap in/out
함수가, 호출되는데
현재 핀토스에서 swap out은 vm_evict_frame
함수에서 호출된다. 즉 물리적 메모리가 부족할 때 그 프레임을 내쫓을 때 실행된다.
vm_get_frame -> vm_evict_frame->vm_get_victim->swap_out
vm_try_handle_fault -> vm_claim_page -> vm_do_claim_page -> swap_in
그리고 swap_in 함수는 Page fault가 발생했을 때, 필요한 페이지가 메모리에 없을 때 호출된다.
디스크의 스왑 영역에서 해당 페이지를 읽어와서 물리 메모리에 로드하는 역할을 한다.
accessed bit
: 페이지가 최근에 접근되었는지를 나타내는 비트 -> 페이지 폴트가 났을 때 페이지 접근 여부 확인할 때 사용됨
dirty bit
: 페이지가 수정되었는지를 나타내는 비트
-> 페이지가 수정되었는지를 확인하며 페이지를 스왑 아웃할 때 디스크에 다시 써야하는지를 결정한다.
dirty bit가 설정되지 않았으면, 수정된 내용이 없으니 그냥 디스크에 기록하지 않고 바로 제거하면 되니까
accessed bit
가 0이면 해당 페이지는 최근에 접근되지 않은 것이니 victim이 된다.
1이면 최근에 접근된 페이지라서 0으로 리셋하고 포인터를 다음 페이지로 이동시킨다.