세리프 따라잡기

WEEK12 - PintOS Project3: Git Book 정리 본문

SW사관학교 정글

WEEK12 - PintOS Project3: Git Book 정리

맑은 고딕 2022. 6. 19. 02:13

※ 전부 정리한 것은 아닙니다! ※

 

Anonymous Page

 

*지연 로딩 페이지 초기화
vm-alloc-page-with-initializer = 새 페이지 초기화하고 컨트롤을 다시 사용자 프로그램으로 반환
> 아직 내용이 없는 페이지에 엑세스 하려고 해서 > 페이지 폴트가 일어남

오류 처리 uninit-initialize가 호출 > 이전 설정 이니셜라이즈 호출
이니셜라이즈 > anon-initializer & file-backed-initializer == 익명 페이지와 파일 지원 페이지를 위한 것

페이지 수명 주기 = initialize->(page_fault->lazy-load->swap-in>swap-out->...)->destroy
수명 주기는 페이지 유형이랑 VM_TYPE에 따라서 다르고, 각 페이지 타입에 따라 전환 프로세스를 구현.

*실행 파일에 대한 지연 로딩
struct uninit_page 구조체는 제공을 해주는데, 생성&초기화&파괴는 알아서~^^
프로세스가 실행 - 즉시 필요한 메모리 부분만 주 메모리에 로드
>> 모든 바이너리 이미지를 한 번에 메모리에 로드하는 Eager loading에 비해 오버헤드 줄임

페이지 폴트 핸들러
먼저 유효한 페이지 폴트인지를 확인함 > 유효하다는 것은 '유효하지 않은 액세스 오류'를 의미합니다.
가짜 폴트면, 일부 내용을 페이지에 로드하고 유저 프로그램에 제어를 반환.

3가지 페이지 폴트 lazy-loaded, swaped-out page, write-protected page.
근데 지금은 lazy-loaded만 신경 ㄱㄱ
lazy-loaded일 경우 이전에 설정한 initializers 중 vm_alloc_page_with_initializer를 호출해 세그먼트를 지연 로드함
>> load_segment 랑 lazy_load_segment 구현해~

재방문 [추가 페이지]
복사 및 정리 작업을 지원하기 위해 추가 페이지 테이블을 수정
→ 프로세스 생성 하거나 파괴할 때 필요
왜 재방문? 위에서 구현한 초기화 기능 중 일부를 사용하고 싶어서~
>> supplemental_page_table_copy 나 supplemental_page_table_kill_ 이거 구현하래
src = source / dst = destination 뜻

supplemental_page_table_copy는 자식이 부모 context 상속해야 할 때 사용
You will need to allocate uninit page and claim them immediately.
>>uninit 페이지를 할당하고 즉시 요청 ㄱㄱ

supplemental_page_table_kill_ 은 보충 페이지 테이블이 보유한 리소스 free
이 함수는 process_exit() 에서 호출됨
페이지 항목을 반복하고 테이블의 페이지에 대해 destroy(page)를 호출
이후 일은 신경 쓸 필요 x, 호출자가 정리해준다고.. [밑 페이지 정리 부분에 설명]

페이지 정리 파트
uninit_destroy 함수에서 지금은 익명 페이지만 처리할 수 있, 나중에 다시 여기 수정할 거
anon_destroy 함수는 익명 페이지의 리소스를 free(해제), 페이지 구조를 명시적으로 해제할 필요x,
호출자가 수행

 


Memory Mapped Files

 

void *mmap (void *addr, size_t length, int writable, int fd, off_t offset);
fd로 열린 파일의 길이가 0바이트인 경우 mmap에 대한 호출이 실패할 수 있습니다. addr이 페이지 정렬되지 않았거나 매핑된 페이지 범위가 실행 가능한 로드 시간에 매핑된 스택 또는 페이지를 포함하여 매핑된 페이지의 기존 집합과 겹치면 실패해야 합니다. Linux에서 addr이 NULL이면 커널은 매핑을 생성할 적절한 주소를 찾습니다. 단순함을 위해 주어진 addr에서 mmap을 시도할 수 있습니다. 따라서 addr이 0이면 일부 Pintos 코드는 가상 페이지 0이 매핑되지 않은 것으로 가정하기 때문에 실패해야 합니다. '길이'가 0일 때도 mmap이 실패해야 합니다. 마지막으로 콘솔 입력 및 출력을 나타내는 파일 설명자는 매핑할 수 없습니다.

메모리 매핑된 페이지도 익명 페이지와 마찬가지로 게으른 방식으로 할당되어야 합니다. vm_alloc_page_with_initializer 또는 vm_alloc_page를 사용하여 페이지 개체를 만들 수 있습니다.

-------------------------------------------------- --------
void munmap (void *addr);
아직 매핑 해제되지 않은 동일한 프로세스에서 mmap에 대한 이전 호출에서 반환된 가상 주소여야 하는 지정된 주소 범위 addr에 대한 매핑을 해제합니다.

모든 매핑은 '종료'를 통하거나 다른 수단을 통해 프로세스가 종료될 때 암시적으로 매핑 해제됩니다. 매핑이 매핑 해제되면 암시적이든 명시적이든 프로세스에 의해 기록된 모든 페이지가 파일에 다시 기록되고 기록되지 않은 페이지는 기록되지 않아야 합니다. 그런 다음 페이지는 프로세스의 가상 페이지 목록에서 제거됩니다.

파일을 닫거나 제거해도 매핑이 해제되지 않습니다. 매핑이 생성되면 Unix 규칙에 따라 munmap이 호출되거나 프로세스가 종료될 때까지 매핑이 유효합니다. 자세한 내용은 열린 파일 제거를 참조하십시오. file_reopen 함수를 사용하여 각 매핑에 대한 파일에 대한 개별적이고 독립적인 참조를 얻어야 합니다.

둘 이상의 프로세스가 동일한 파일을 매핑하는 경우 일관된 데이터를 볼 필요가 없습니다. Unix는 두 매핑이 동일한 물리적 페이지를 공유하도록 하여 이를 처리하고 mmap 시스템 호출에는 클라이언트가 페이지가 공유 또는 비공개(즉, copy-on-write)인지 여부를 지정할 수 있는 인수도 있습니다.

필요에 따라 vm/vm.c에서 vm_file_init 및 vm_file_initializer를 수정할 수 있습니다.
-------------------------------------------------- --------
void vm_file_init (void);
파일 지원 페이지 하위 시스템을 초기화합니다. 이 기능에서는 파일 백업 페이지와 관련된 모든 것을 설정할 수 있습니다.

bool file_backed_initializer (struct page *page, enum vm_type type, void *kva);
파일 지원 페이지를 초기화합니다. 이 함수는 먼저 'page->operations'에서 파일 지원 페이지에 대한 핸들러를 설정합니다. 메모리를 지원하는 파일과 같은 페이지 구조에 대한 일부 정보를 업데이트할 수 있습니다.

static void file_backed_destroy (struct page *page);
연결된 파일을 닫아 파일 백업 페이지를 파괴합니다. 내용이 더러우면 변경 사항을 파일에 다시 기록하십시오. 이 함수에서 페이지 구조를 해제할 필요가 없습니다. file_backed_destroy의 호출자가 이를 처리해야 합니다.

 


Swap In/Out

 

제거를 위해 선택한 페이지는 익명 페이지 또는 파일 지원 페이지일 수 있습니다. 이 섹션에서는 각 경우를 처리합니다. [page type을 구분해서 넘겨줘야 하는 걸까?]

모든 스와핑 작업은 명시적으로 호출되지 않고 함수 포인터로 호출됩니다. 그들은 struct page_operations file_ops의 구성원이며, 각 페이지의 초기화 프로그램에 대한 작업으로 등록됩니다.

Modify vm_anon_init and anon_initializer in vm/anon.c ==  vm_anon_init 랑 anon_initializer 수정해야함

구현순서
1. vm_anon_init 
2. anon_swap_out
3. anon_swap_in
4. anon_initializer

bool anon_initializer (struct page *page, enum vm_type type, void *kva);
페이지를 교체하려면 교체해야 하므로 anon_swap_in을 구현하기 전에 anon_swap_out을 구현하는 것이 좋습니다. 데이터 내용을 스왑 디스크로 이동하고 안전하게 메모리로 가져와야 합니다.

static bool anon_swap_in (struct page *page, void *kva);
디스크에서 메모리로 데이터 내용을 읽어 스왑 디스크에서 익명 페이지로 스왑합니다. 데이터의 위치는 페이지가 스왑 아웃될 때 페이지 구조에 스왑 디스크가 저장되어 있어야 합니다. 스왑 테이블을 업데이트하는 것을 잊지 마십시오(스왑 테이블 관리 참조).

static bool anon_swap_out (struct page *page);
메모리에서 디스크로 내용을 복사하여 익명 페이지를 스왑 디스크로 교체합니다. 먼저 스왑 테이블을 사용하여 디스크에서 여유 스왑 슬롯을 찾은 다음 데이터 페이지를 슬롯에 복사합니다. 데이터의 위치는 페이지 구조에 저장해야 합니다. 디스크에 여유 슬롯이 더 이상 없으면 커널을 패닉 상태로 만들 수 있습니다.
------------------------------------------------
File-Mapped Page

파일 백업 페이지의 내용은 파일에서 가져오기 때문에 mmaped 파일을 백업 저장소로 사용해야 합니다. 즉, 파일 지원 페이지를 제거하면 매핑된 파일에 다시 기록됩니다. vm/file.c에서 file_backed_swap_in, file_backed_swap_out을 구현합니다. 설계에 따라 file_backed_init 및 file_initializer를 수정할 수 있습니다.


파일에 내용을 다시 기록하여 페이지를 swap out 합니다. page가 dirty한지 먼저 확인하는 것이 좋습니다. not dirty하면 파일의 내용을 수정할 필요가 없습니다. 페이지를 swap out 한 후 page의 dirty bit를 끄는 것을 잊지 마십시오.



/home/ubuntu/pintos-kaist/include/vm/vm.h
Q. vm.h에서 우리가 struct page에서 swap_slot이라는 구조체 멤버를 설정해주었는데 이거 쓰는 건가?? 의문🙄

A. 써! 다만 page 구조체에서 쓰지 않고 해당 struct에다가 옮겨서 쓰는 방식으로 바꿈!!

Comments