미소를뿌리는감자의 코딩
[Pintos_project3 (15)] do_mmap 본문
728x90
1. 개요
do_mmap의 경우엔, file_backed 페이지에 대해서 PM와 mapping을 시켜주는 함수이다.
2. 본문
mmap함수의 경우엔, do_mmap을 하기 전에 여러 인자들에 대해서 유효성 검사를 하는 것이 주된 목표라고 할 수 있다.
주석 처리를 통해 각각의 코드의 의미를 적어보았다.
// userprog/syscall.c
/** Project 3: Memory Mapped Files - Memory Mapping */
void *mmap(void *addr, size_t length, int writable, int fd, off_t offset) {
/* addr = 매핑을 시작할 가상 메모리 주소
* offset = 파일의 매핑 시작 위치
*/
if (!addr || pg_round_down(addr) != addr || is_kernel_vaddr(addr) || is_kernel_vaddr(addr + length))
return NULL;
/* 각각의 조건에 대해서 확인해보자.
* pg_round_down(addr) != addr ; 메모리 매핑 주소가 페이지 경계에 정렬되어 있지 않을 때
* is_kernel_vaddr(addr) ; 커널 전용 주소가 사용되는 지 확인. 매핑 가상 주소가 커널 전용 주소이면 안됨.
* is_kernel_vaddr(addr + length) ; 범위 끝이 커널 주소인지 확인. 즉, 시작과 끝이 유저 전용 주소인지 확인.*/
if (offset != pg_round_down(offset) || offset % PGSIZE != 0) // offset 또한 페이지 경계에 정렬되어 있어야 함.
return NULL;
if (spt_find_page(&thread_current()->spt, addr)) // 이미 현재 addr가 page_table에 매핑이 되어 있다면 실패. 중복되지 않아야 함.
return NULL;
struct file *file = process_get_file(fd); // file descriptor로 file 가져오기.
if ((file >= STDIN && file <= STDERR) || file == NULL) // 파일이 표준 입력/출력/오류 라면 안되므로 이를 확인, fd가 유효한지 확인.
return NULL;
if (file_length(file) == 0 || (long)length <= 0) // 매핑할 파일의 크기 0인 경우 실패. 매핑할 길이가 0 이하인 경우도 실패.
return NULL;
return do_mmap(addr, length, writable, file, offset);
}
mmap이 매핑 가능 조건을 확인하는 함수였다면, do_mmap은 실제 매핑을 진행하는 함수라고 할 수 있다.
이 또한 주석 처리를 통해 코드 의미를 적어두었다.
/* Do the mmap / mmap이 매핑 가능 조건을 확인하는 함수였다면, do_mmap은 실제 매핑을 진행하는 함수.*/
void *do_mmap(void *addr, size_t length, int writable, struct file *file, off_t offset) {
lock_acquire(&filesys_lock); // 파일 시스템에 동시 접근하지 않도록 잠금.
struct file *mfile = file_reopen(file); //reopen을 통해 파일 핸들을 복제해서 독립적으로 파일을 사용할 수 있도록 설정.
void *ori_addr = addr; // 매핑이 성공했을 때 반환할 원래 주소.
size_t read_bytes = (length > file_length(mfile)) ? file_length(mfile) : length;
size_t zero_bytes = PGSIZE - read_bytes % PGSIZE;
ASSERT((read_bytes + zero_bytes) % PGSIZE == 0); // 페이지 단위인지 확인.
ASSERT(pg_ofs(addr) == 0); // 시작 주소가 페이지 경계인지 확인.
ASSERT(offset % PGSIZE == 0);
struct aux *aux;
while (read_bytes > 0 || zero_bytes > 0) {
// 페이지 단위로 page_read_bytes와 page_zero_bytes를 사용.
size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
size_t page_zero_bytes = PGSIZE - page_read_bytes;
aux = (struct aux *)malloc(sizeof(struct aux)); // aux 동적 할당.
if (!aux)
goto err;
aux->file = mfile; // file 정보
aux->offset = offset; // offset 정보
aux->page_read_bytes = page_read_bytes; // 바이트 정보
if (!vm_alloc_page_with_initializer(VM_FILE, addr, writable, lazy_load_segment, aux)) { // vm_alloc_page_with_initializer로 페이지 할당.
goto err;
}
read_bytes -= page_read_bytes; // 처리한 바이트 수를 전체 바이트 수에서 빼주기.
zero_bytes -= page_zero_bytes;
addr += PGSIZE; // 다음에 읽을 addr를 찾기 위해 PGSIZE를 더해줌.
offset += page_read_bytes;
}
lock_release(&filesys_lock); // acquire했던 lock 놔주기
return ori_addr; // 할당 성공 시, 주소 반환
err:
free(aux);
lock_release(&filesys_lock);
return NULL; // 실패 시, NULL 반환.
}
3. 결과
728x90
'정글 일지' 카테고리의 다른 글
[Pintos_project (17)] vm_file_init, file_backed_initializer (0) | 2024.12.03 |
---|---|
[Pintos_project3 (16)] do_munmap, file_backed_destroy (0) | 2024.12.03 |
[Pintos_project3 (14)] vm_try_handle_fault, vm_stack_growth (0) | 2024.12.03 |
[Pintos_project3 (13)] uninit_destory, anon_destory (0) | 2024.12.02 |
[Pintos_project3 (12)] supplemental_page_table_copy, supplemental_page_table_kill (0) | 2024.12.02 |