정글에서 온 개발자
정글 pintOS project3 - mmap. file_reopen 잡아주기 본문
기존 mmap 코드
void *
do_mmap (void *addr, size_t length, int writable,
int fd, off_t ofs) {
//에러 처리
void *va = pg_round_down(addr);
if(length == 0 || addr == 0 || va != addr
|| fd == 0 || fd == 1){
return NULL;
}
struct file *file = thread_current()->fdt[fd]; //이 부분
off_t read_bytes = file_length(file);
if(read_bytes <= 0 || read_bytes - ofs <= 0){
return NULL;
}
read_bytes-=ofs;
//가상주소가 잡혀있는 페이지인지 확인
int pages = read_bytes % PGSIZE +1 ;
for(int i = 0; i < pages; i++){
if(spt_find_page(&thread_current()->spt, va + i*PGSIZE) != NULL){
return NULL;
}
}
//페이지들에 맵핑(lazy load)
while (read_bytes > 0) {
/* Do calculate how to fill this page.
* We will read PAGE_READ_BYTES bytes from FILE
* and zero the final PAGE_ZERO_BYTES bytes. */
size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
size_t page_zero_bytes = PGSIZE - page_read_bytes;
/* TODO: Set up aux to pass information to the lazy_load_segment. */
struct seg_arg *args = calloc(1, sizeof(struct seg_arg));
if(args == NULL){
PANIC("Memory allocation failed\n");
return false;
}
args->file = file;
args->ofs = ofs;
args->page_read_bytes = page_read_bytes;
args->page_zero_bytes = page_zero_bytes;
args->total_page = pages; //munmap을 위해 카운트
void *aux = args;
if(!vm_alloc_page_with_initializer(VM_FILE, va, writable, lazy_load, aux)){
exit(-1);
}
read_bytes -= page_read_bytes;
va += PGSIZE;
ofs += page_read_bytes;
}
return addr;
}
- 깃북에 나온 각종 에러처리를 한다.
- 기존에 잡혀있는 페이지들인지 supplement_page_table을 검사해 확인한다.
- 기존 load_segment 함수를 참고하여 lazy_load하도록 로직을 짰다.
기존 결과
- mmap-read 테스트는 잘 통과한다.
- mmap-close 는 통과하지 못한다.
원인 분석
- 위 파일을 가져오는 부분 코드에 따르면 ,mmap한 주소에는 fd가 가리키고 있는 파일이 맵핑되어있다.
- mmap명령어를 쓰더라도, lazy load이기 때문에 아직 해당 페이지가 있는 물리주소에는 파일의 내용이 써있지 않은 상태다.
- lazy load가 되기 전에 file close를 해버리면, 추후 lazy load시 참고해야할 file이 사라져 버린다.
- 그래서 memcmp시, 비교를 하려고 lazy load를 하면 읽을 file이 없어 exit(-1) 한다.
해결 방법
- 깃북 munmap 파트에 file_reopen을 활용하라고 써 있다.
Closing or removing a file does not unmap any of its mappings. Once created, a mapping is valid until munmap is called or the process exits, following the Unix convention. See Removing an Open File for more information. You should use the file_reopen function to obtain a separate and independent reference to the file for each of its mappings.
- 코드를 다음과 같이 바꾸면 패스한다.
//에러처리
void *va = pg_round_down(addr);
if(length == 0 || addr == 0 || va != addr
|| fd == 0 || fd == 1){
return NULL;
}
struct file *file = file_reopen(thread_current()->fdt[fd]); //close해도 file 살아있게
off_t read_bytes = file_length(file);
if(read_bytes <= 0 || read_bytes - ofs <= 0){
return NULL;
}
read_bytes-=ofs;
'TIL' 카테고리의 다른 글
spring (boot) quick start 막혔던 것 - 쉬움 (0) | 2023.12.31 |
---|---|
정글 pintos-project3 table_kill시 hash_destroy하면 안되는 이유 (1) | 2023.12.28 |
정글 pintOS project3 page-linear 디버깅 (0) | 2023.12.25 |
정글pintOS project3 - Anonymous page 디버깅 (0) | 2023.12.23 |
[pintOS]-FIFO 궁금했던 점 분석 (1) | 2023.12.05 |