void *mmap(...)
시스템 콜전반적인 구현 계획
swap out()
→ mmap()은 Disk에 file을 backup하고, 매핑해주는 함수??
→ addr, length, fd, offset등이 필요하다.
→ file list[fd]로 해당 file을 찾는다
→ offset ↔ length까지 read()해서 Disk에 있는 file에 write()한다??
→ swap in() 실행
→ get_disk_file() - 대충 disk에 있는 file addr를 반환해주는 함수
→ struct thread의 mapping list
→ …
file copy는 큰 주소에서 작은 주소로 복사가 이루어진다. 복사하고 난 후에 file backed()을 하기 위해서 read at()을 진행해야 하는데 위 상태에서 보면 addr은 가장 낮은 주소이다. addr을 위로 올라가면서 read at()을 진행해야 할까?
if → addr == 0, length == 0, spt_find() ≠ NULL, fd == 0, fd == 1, addr % 4096 ≠ 0이라면 NULL을 반환한다.
file_reopen()
page = do_mmap()
return addr
// 1. addr이 0인지 check한다
// 2. fd가 0이나 1이 아닌지 check한다
// 3.file 용량이 0인지 check 한다.
// 4. addr의 page에 spt가 없어야 한다?
// 5. addr aline인있는 지 c
void *mmap (void *addr, size_t length, int writable, int fd, off_t offset)
{
struct thread *curr = thread_current();
if (addr == NULL || length == 0 || fd == 0 || fd == 1 || (uint64_t) addr % 4096 != 0 || spt_find_page(&curr->spt, addr)) { // 이건 맞다고 가정하고
return NULL;
}
struct file *file = process_get_file_by_fd(fd);
void *upage = do_mmap(addr, length, writable, file, offset);
return upage;
}
목표 : lazy load할 때 필요한 lazy aux를 초기화하고, page fault시점에 file read at()을 진행한다.
(mmap-over-stk) begin
(mmap-over-stk) open "sample.txt"
(mmap-over-stk) open "sample.txt": FAILED
mmap-over-stk: exit(1)
void
test_main (void)
{
int handle;
uintptr_t handle_page = ROUND_DOWN ((uintptr_t) &handle, 4096);
CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
CHECK (mmap ((void *) handle_page, 4096, 0, handle, 0) == MAP_FAILED,
"try to mmap over stack segment");
}
file open()에서 fail이 난다. 왜 발생하는 것일까?
syscall.c의 open()은 내가 건든적이 없으니 아닌 것 같고.
struct lazy_aux_file_backed *aux = malloc(sizeof(struct lazy_aux_file_backed));
aux->file = file_reopen(file);
aux->writable = writable;
aux->length = length > PGSIZE ? PGSIZE : length;
aux->offset = offset;
여기서 문제가 발생한 건가?
int open(const char *filename) {
check_address(filename); // 이상한 포인터면 즉시 종료
dprintfe("[open] check_address 바로 다음 라인\n");
struct file *file_obj = filesys_open(filename);
dprintfe("[open] filesys_open 바로 다음 라인\n");
if (file_obj == NULL) {
return -1;
}
int fd = process_add_file(file_obj);
if (fd == -1) { // fd table 꽉찬 경우 그냥 닫아버림
file_close(file_obj);
file_obj = NULL;
}
dprintfe("[open] open() 마지막 라인\n");
return fd;
}
여기서 open()의 마지막 라인이 실행이 안된다…
잘 되던게 안될 수는 없다!! 분명 뭔가가 있는 것이다. 솔직히 약간 모르겠지만 아까 팀원이 file name을 잘못 줘서 터졌다는 걸 들었다. 바로 file name 수정한다!!!
void *mmap (void *addr, size_t length, int writable, int fd, off_t offset)
{
struct thread *curr = thread_current();
if (addr == NULL || length == 0 || fd == 0 || fd == 1 || (uint64_t) addr % 4096 != 0 || spt_find_page(&curr->spt, addr)) { // 이건 맞다고 가정하고
return NULL;
}
struct file *file = process_get_file_by_fd(fd);
void *upage = do_mmap(addr, length, writable, file, offset);
return upage;
}
file 찾아서 반환했지만 실패…
struct lazy_aux_file_backed *aux = malloc(sizeof(struct lazy_aux_file_backed));
aux->file = file_reopen(file);
aux->writable = writable;
aux->length = length > PGSIZE ? PGSIZE : length;
aux->offset = offset;
여기서 reopen()이 반복되면서 하나의 File 중복 참조해서 문제가 생기는 걸까?
pass tests/vm/mmap-over-stk
이거 open()에서 문제가 생긴 것이 아니다. printf()를 끄지 않고 돌렸는데 이때 출력용으로 사용한 포인터에서 문제가 생긴 것 같다.
/* Do the mmap */
void *
do_mmap(void *addr, size_t length, int writable, struct file *file, off_t offset)
{
// 1. addr로부터 페이지 생성
// 1-1. lazy_load, aux 초기화해서 넘겨주기.
// 1-2. 복사(length, offset, 등등) 이거 바로 해줘요? 그럼 또 lazy 아니잖아. -> 이 내용이 lazy_load에서 타입 체크후에 복사 바로 하면 되지 않겠나.
// 1-3. 나머자 내용은 0으로 채워야 함.
void *start_addr = addr;
while (length > 0)
{
struct lazy_aux_file_backed *aux = malloc(sizeof(struct lazy_aux_file_backed));
aux->file = file_reopen(file);
aux->writable = writable;
aux->length = length > PGSIZE ? PGSIZE : length;
aux->offset = offset;
if (!vm_alloc_page_with_initializer(VM_FILE, addr, writable, lazy_load_file_backed, aux))
{
// page clean??
free(aux);
while(start_addr < addr){
vm_dealloc_page(spt_find_page(&thread_current()->spt, addr));
addr -= PGSIZE;
}
file_close(file);
return NULL;
}
// 쓴 만큼 offset, length 업데이트.
length -= PGSIZE;
offset += PGSIZE;
addr += PGSIZE;
}
struct mmap_file *mmap_file = malloc(sizeof(struct mmap_file));
mmap_file->start_addr = start_addr;
list_push_back(&thread_current()->mmap_list, &mmap_file->elem);
return start_addr;
}