오늘도 어제에 이어 깃북을 주로 분석해보는 시간을 가졌다. 이해한 바를 기반으로 나만의 언어로 아래와 같이 노션에 1차적으로 정리해두었고, TIL에서 다시 한 번 정리하며 전체적으로복습해보려고 한다. 이번 프로젝트는 Introduction부터 양이 상당히 많다😋
supplemental page table은, page table에 각 페이지 관련 추가 데이터를 보충해주는 것 을 말한다. 이는 page table의 포맷에서 야기되는 제약으로 인해 필요하다.
supplemental page table 도 그냥 단순히 page table 로 지칭할 수 있는데, 구분을 위해서 supplemental 이란 단어를 붙여주자.
supplemental page table 은 최소 2가지 목적을 위해 사용된다.
1) page fault 발생 시, 커널이 fault를 유발한 virtual page를 supplemental page table에서 찾아낸다. 어떤 데이터가 들어있어야 했는지 밝혀내기 위함이다.
2) 커널은 어떤 프로세스가 종료될 때 supplemental page table에게 어떤 resource들을 free해줄지 지시한다.
supplemental page table을 구성하는데는 segment로 구성할지, page로 구성할지의 2가지 방식이 있다. 이 때, segment란 executable이나 memory-mapped file을 포함한 메모리 영역과 같은 어떤 연속된 page의 그룹 을 말한다.
위에서 정리한 supplemental page table을 활용하는 것들 중 가장 중요한 것이 바로 page fault handler 이다. 이전 프로젝트에서는 page fault가 언제나 커널이나 유저 프로그램의 버그를 나타내 주었지만, 이번 프로젝트에선 단순히 page가 file과 swap slot 중 어디에서 page를 가져와야 하는지만 나타낼수도 있다.
따라서 위와 같은 경우를 처리할 수 있도록, 대략적으로 다음과 같은 사항들을 수행할 수 있는 정교한 page fault handler를 이번 프로젝트에서 구현해주어야 한다.
frame table은 PintOS가 eviction policy를 효율적으로 시행할 수 있도록 한다. 만약 비어있는 frame이 하나도 없는 경우, frame table이 축출할 page를 골라내준다.
user page 를 위해 사용되는 frame은 반드시 "user pool"에서 얻어와야 한다. 만약 "kernel pool"에서 할당을 받는 경우, 예기치 못하게 몇몇 test가 실패할 가능성이 있기 때문이다. PintOS에선 palloc_get_page(PAL_user)를 호출함으로써 user pool에서 frame을 얻을 수 있다.
frame table에 있어, 가장 중요한 액션은 'unused frame을 획득하는 것' 이 되겠다. 만약, 모든 frame이 비어있지 않은 경우에는 eviction 을 진행해야 한다. (거기에 더해 만약 swap slot을 할당하지 않고는 eviction을 진행할 수 없는 상황인데 swap마저 full인 경우가 생긴다면, 커널을 패닉시켜야 한다.)
eviction은 위와 같은 절차에 따라 진행된다는 것을 확인하자!
PTE 내에는 page replacement algorithm 구현에 활용할 수 있는 한 쌍의 비트가 있는데, 이게 바로 accessed bit 와 dirty bit 이다.
read or write의 경우, CPU는 PTE 내의 accessed bit 을 1로 설정한다.
write의 경우, CPU는 PTE 내의 dirty bit 를 1로 설정한다.
위의 accessed & dirty bits와 관련하여, 'aliases' 에 관련된 문제를 해결해주어야 한다. aliases 란 동일한 하나의 frame을 참조하는 2개 혹은 그 이상의 page를 말하며, 이 때 참조하는 frame은 aliased frame 이라고도 한다.
문제는 aliased frame에 액세스가 발생하는 경우, 해당 frame을 참조하는 여러 page 중 해당 액세스에 활용된 오직 하나의 page에 대해서만 accessed & dirty bits가 수정될 수 있다는 것이다.
이를 해결하기 위해선, 해당 프레임을 참조하는 모든 virtual page에 대한 accessed & dirty bits를 일괄적으로 수정해주든지, 혹은 커널이 user virtual address를 통해서만 user data에 접근하도록 함으로써 해결해주어야 한다.
참고로 이 accessed & dirty bits에 대해선 부록 PAGE TABLE 에 위와 같이 추가적인 내용이 담겨있어서, 역시나 같이 살펴보고 정리해놓았다!
swap table을 활용하면 사용 중인 swap slot과 비어있는 swap slot을 추적할 수 있다.
만약 frame에서 한 페이지를 축출해 swap partition으로 옮기려고 한다면, swap table은 비어있는 하나의 swap slot을 선택할 수 있어야 한다.
또한, 어떤 swap slot에 들은 페이지가 다시 읽히거나(read back) 스왑된 page의 주인 프로세스가 종료된 경우라면, swap table에서 해당 swap slot을 free 해줄 수 있어야 한다.
swap slot은 미리 할당되는 것이 아니라, 오직 축출이 발생함으로써 실제로 필요하게 되는 경우에야 비로소 천천히 할당되어야 한다. 또한, swap slot은 특정 페이지를 저장하기 위해 예약되어서는 안 된다.
파일 시스템은 주로 READ, WRITE 시스템 콜에 의해 액세스되지만, MMAP 시스템 콜에 의해서도 액세스된다. MMAP 시스템 콜이 불리면, 파일을 가상 페이지에 매핑해주게 된다. 매핑이 완료되고 나면, 프로그램은 파일의 데이터에 대해서 직접 memory instruction을 사용할 수 있게 된다.
memory mapped file을 잘 활용하면, 어떤 메모리가 사용되는지 확인할 수 있다. 이를 추적할 수 있도록 mmap을 구현해주는 것이 필요하다.
이렇게 Introduction 정리를 마무리했다:) 아직은 헷갈리는 내용도 많고, Virtual Memory 전반에 대해서 이해가 많이 부족한 느낌이다. 이번에야말로 벽에 부딪히는건가 싶기도 하지만, 내 스스로의 한계를 실험하는 일은 언제나 즐겁다. 일단 CSAPP 교재 등 주어진 기본 자료를 충실히 정독하고 찬찬히 살펴봐야겠다. 포기하기엔 아직 시간이 충분히 많다 !