Anonymous Page까지 구현을 하고,
make check를 돌려보았지만, read-boundary의 테스트 케이스가 통과하지를 못했다.
디버깅을 돌려보니 check_address 함수 내에 pml4_get_page 부분이 자꾸 터지는 것을 보았다.
이 부분에 대해 나와 비슷한 문제를 겪는 사람들이 있어서 이 부분에 대해서 포스팅을 해본다 !
먼저 테스트 파일들을 확인해보자.
Test Case : read-boundary.c 파일
buffer = get_boundary_area () - sizeof sample / 2;
byte_cnt = read (handle, buffer, sizeof sample - 1);
- get_boundary_area 함수는 페이지의 경계 값을 가져옴
- sample.txt 파일 전체 크기를 반으로 나누어 경계값에 빼줌
- ex) Page1과 Page2의 경계가 있다면, sample.txt 반을 각각의 Page에 들어가도록
- 아래와 같은 느낌
주소 : 0x1000 0x1FD1 ... 0x1FFF | 0x2000 ... 0x2032 ... 0x2FFF
페이지 : [ 페이지 A (0x1000 ~ 0x1FFF) ] | [ 페이지 B (0x2000 ~ 0x2FFF) ]
데이터 흐름 : [ 빈 공간 buffer → 데이터 → ] | [ → 데이터 계속 저장 → 빈 공간 ]
이번에는 오류가 발생하는 함수 부분을 살펴보자.
check_address 함수 (syscall.c)
#ifndef VM
void check_address(void *addr) {
if (is_kernel_vaddr(addr) || addr == NULL || pml4_get_page(thread_current()->pml4, addr) == NULL)
exit(-1);
}
#endif
#ifdef VM
void check_address(void *addr) {
if (is_kernel_vaddr(addr) || addr == NULL )
exit(-1);
spt_find_page(&thread_current()->spt,addr);
}
#endif
- VM 부분과 이외 프로젝트로 나눠짐 (이외 프로젝트 부분은 다루지 않음)
- VM 부분에서 check_address 부분에 pml4_get_page 부분이 사라지고, spt_find_page 함수가 추가해야 함
- VM에 Lazy Loading 때문에 pml4로 가면 안되고 spt에서 찾아야함
read 함수 (syscall.c)
int read(int fd, void *buffer, unsigned length) {
thread_t *curr = thread_current();
check_address(buffer);
. . .
return bytes;
}
궁금증❗
단순히 spt에서 page를 찾는 spt_find_page 함수인데, check_address에 쓰는게 의미가 있나 ?
(check_address 부분에 spt_find_page를 쓰지 않으면 read-boundary 테스트 케이스 fail이 됨)
load_segment는 프로그램 실행 시 초기화 과정에서 실행 파일의 필요한 부분을 SPT에 등록한다.
이때 모든 페이지가 load_segment에서 SPT에 등록되지 않는다.
보통 첫 번째 페이지는 SPT에 등록되지만 두번째 페이지는 Lazy Loading 때문에 SPT에 등록되지 않을 수 있다.
실행 도중 접근 가능성이 낮은 페이지나 동적으로 확장되는 영역(예: 스택, 힙, 추가 데이터)은 초기화 단계에서 등록되지 않을 수도 있다.
read-boundary 테스트 케이스 같은 경우는 두 개 이상의 페이지에 걸쳐 데이터를 복사해서 spt_find_page 없이는 fail이 뜨게 되는 것이다.
그러면 spt_find_page의 역할을 뭘까 ?
간단히 말하자면, 페이지 폴트를 발생시켜 해당 주소에 대한 정보를 SPT에 추가해준다.
즉, SPT에 등록되지 않은 페이지를 Page Fault를 통해서 데이터를 로드한다.
만일 단일 페이지 내에서 작업이라면 굳이 spt_find_page 함수가 필요 없다.
SPT에 등록된 페이지만 접근하므로 경계 조건에 대한 특별한 처리가 필요 없기때문이다.
이해를 위한 예시
- 첫 번째 페이지: 초기화된 데이터(.data)를 포함.
- 두 번째 페이지: 경계 이후의 확장 영역이거나 아직 접근되지 않은 부분.
+----------+----------+
| Page 1 | Page 2 |
| 등록됨 | 미등록 |
+----------+----------+
^ 경계를 넘어 Page 2 접근 시:
- SPT에서 Page 2 정보를 찾지 못함 -> 페이지 폴트 발생.
- 페이지 폴트 핸들러에서 Page 2를 처리 후 등록.
이렇게하면 왜 spt_find_page를 써야하는지를 알 수 있다.
'크래프톤 정글' 카테고리의 다른 글
Pintos Project3 - VM 시스템 초기화 (2) | 2024.12.05 |
---|---|
Pintos Project3 - Virture Memory 키워드 (1) | 2024.12.02 |
Pintos Project3 - Page Fault Handler (Page Fault 전반적인 과정 이해하기) (0) | 2024.12.02 |
Pintos Project3 - VA와 디스크 데이터 매핑 과정 이해하기 (0) | 2024.12.01 |
Pintos Project2 - User Program 흐름 잡기 (0) | 2024.12.01 |