์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- ์ ๋ํฐ
- ํฌ๋ํํค์ ๊ธ4๊ธฐ
- BFS
- anonymous page
- ๋ค์ต์คํธ๋ผ
- project3
- ํ์ด์ฌ
- ํํ ์ค
- ์ถ์ํด๋์ค์์ธํฐํ์ด์ค
- ์๊ณ ๋ฆฌ์ฆ์์ -๋๋น์ฐ์ ํ์2
- ๋คํธ์ํฌ
- ํฌ๋ํํค์ ๊ธ
- c#
- kraftonjungle
- ์ ์-์ ํฌ
- User Stack
- ํฌ๋ํํค ์ ๊ธ
- KRAFTON JUNGLE
- ์๊ณ ๋ฆฌ์ฆ
- pintos
- TiL
- ๋ฐฑ์ค
- ์ค๋ธ์
- ์ฐ๊ฒฐ๋ฆฌ์คํธ
- ์ด๋ฒคํธ ํจ์ ์คํ ์์
- Unity
- C
- ํฌ๋ํํค ์ ๊ธ 4๊ธฐ
- ํฐ์คํ ๋ฆฌ์ฑ๋ฆฐ์ง
- 4๊ธฐ
- Today
- Total
๋ง๊ฐ๋ก๊ทธ
ํฌ๋ํํค ์ ๊ธ WEEK11 DAY 87 - PintOS Project3 - Memory Mapped Files (mmap) ๋ณธ๋ฌธ
ํฌ๋ํํค ์ ๊ธ WEEK11 DAY 87 - PintOS Project3 - Memory Mapped Files (mmap)
habbn 2024. 4. 3. 01:20๐2024. 04.02
Memory Mapped Files๋ ํ์ผ์ ๊ธฐ๋ฐ์ผ๋ก ๋งคํํ๋ ํ์ด์ง๋ฅผ ๊ตฌํํ๋ ๊ฒ์ด๋ค.
ํ์ผ๊ณผ ๋ฉ๋ชจ๋ฆฌ ๋งคํ์ System Call์ธ mmap()์ ํตํด ์ด๋ฃจ์ด์ง๋ค.
Pintos์์๋ vm/file.c์ do_mmap()์ ์ด์ฉํด์ ๋งคํ์ ์ํํ๋๋ฐ, ๊ทธ ์ด์ ์ mmap()์ ์ ๋ฌ๋ ์ธ์๋ค์ ๋ํ ๊ฒ์ฆ์ด ๋จผ์ ์ด๋ฃจ์ด์ ธ์ผ ํ๋ค.
์์คํ ์ฝ mmap()
1. offset์ ๊ฐ์ด PGSIZE์ ์๋ง๊ฒ align๋์ด ์์ง ์์ ๊ฒฝ์ฐ
2. addr์ด NULL์ด๊ฑฐ๋, addr์ด page-aligned๋์ง ์์๊ฑฐ๋ kernel ์์ญ์ธ ๊ฒฝ์ฐ
3. ๋งคํํ๋ ค๋ ํ์ด์ง๊ฐ ์ด๋ฏธ ์กด์ฌํ๋ ํ์ด์ง์ ๊ฒน์น ๋ (=spt์ ์กด์ฌํ๋ ํ์ด์ง์ผ ๋)
4. ์ฐพ๋ ํ์ผ์ด ๋์คํฌ์ ์๋ ๊ฒฝ์ฐ
5. fd๋ก ์ด๋ฆฐ ํ์ผ์ ๊ธธ์ด๊ฐ 0๋ฐ์ดํธ์ธ ๊ฒฝ์ฐ, length๊ฐ 0์ธ ๊ฒฝ์ฐ
6. ์ฝ์ ์ ์ถ๋ ฅ๊ณผ ์ฐ๊ด๋ ํ์ผ ๋์คํฌ๋ฆฝํฐ ๊ฐ์ธ ๊ฒฝ์ฐ
๋งคํ์ด ์ด๋ฃจ์ด์ง ์ ์๋ค.
์์ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๊ณ , do_mmap()์ ํธ์ถํด์ ํ์ผ๊ณผ ๊ฐ์ ์ฃผ์ ๊ฐ์ ๋งคํ์ ์งํํ๊ณ , ๋งคํ๋ ๊ฐ์ ์ฃผ์๋ฅผ ๋ฐํํ๋ค.
void *mmap (void *addr, size_t length, int writable, int fd, off_t offset){
//offset์ ๊ฐ์ด PGSIZE์ ์๋ง๊ฒ aling๋์ด ์์ง ์์ ๊ฒฝ์ฐ
if(offset % PGSIZE != 0)
return NULL;
//addr์ด NULL์ด๊ฑฐ๋, addr์ด page-aligned๋์ง ์์๊ฑฐ๋ kernel ์์ญ์ธ ๊ฒฝ์ฐ
if(addr == NULL || addr == 0 || addr != pg_round_down(addr) || !is_user_vaddr(addr || !is_user_vaddr(addr + length)))
return NULL;
// ๋งคํํ๋ ค๋ ํ์ด์ง๊ฐ ์ด๋ฏธ ์กด์ฌํ๋ ํ์ด์ง์ ๊ฒน์น ๋(==SPT์ ์กด์ฌํ๋ ํ์ด์ง์ผ ๋)
if(spt_find_page(&thread_current()->spt, addr))
return NULL;
//์ฐพ๋ ํ์ผ์ด ๋์คํฌ์ ์๋ ๊ฒฝ์ฐ
struct file *target = get_file_from_fd(fd);
if(target == NULL)
return NULL;
//fd๋ก ์ด๋ฆฐ ํ์ผ์ ๊ธธ์ด๊ฐ 0๋ฐ์ดํธ์ธ ๊ฒฝ์ฐ, length๊ฐ 0์ผ ๋๋ ์คํจ
if( file_length(target) == 0 || (long long)length <= 0)
return NULL;
//์ฝ์ ์
์ถ๋ ฅ๊ณผ ์ฐ๊ด๋ ํ์ผ ๋์คํฌ๋ฆฝํฐ ๊ฐ์ธ ๊ฒฝ์ฐ
if(fd == 0 || fd == 1)
return NULL;
return do_mmap(addr, length, writable, target, offset);
}
do_mmap()
file-backed page๋ anonymous page์ ๋ง์ฐฌ๊ฐ์ง๋ก lazy loading์ ์ด์ฉํ๋ค.
page๊ฐ ์ด๊ธฐํ๋ ๋ ํ์ผ์์ ๋ด์ฉ์ ์ฝ์ด์ฌ ์ ์๋๋ก lazy_load_segment์ ๋ก๋ฉํ ๋ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ํ์ด์ง์ ์ ์ฅํด๋์ด์ผ ํ๋ค.
ํ์ผ์ ๋ํ ๋ ๋ฆฝ์ ์ธ ์ฐธ์กฐ
์ ๋์ค ๊ท์น์ ๋ฐ๋ผ ๋งคํ์ ๋งคํ์ ํด์ ํ๋ munmap์ด ํธ์ถ๋๊ฑฐ๋ ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ๋ ๋๊น์ง ์ ํจํ๋ค.( ํ์ผ์ ๋ซ๊ฑฐ๋ ์ ๊ฑฐํด๋ ๋งคํ์ ํด์ ๋์ง ์๋๋ค.)
๋์ผํ ํ์ผ์ ๋ํด ์ฌ๋ฌ ํ๋ก์ธ์ค์ ์ํด ์ฌ๋ฌ ๊ฐ์ ๋งคํ์ด ์กด์ฌํ๋ค๊ณ ์๊ฐํด๋ณด์. ์ด๋ ํ ํ๋ก์ธ์ค์์ ์ด ํ์ผ์ ๋ซ๊ฑฐ๋ ์ ๊ฑฐํ๋ฉด ๋ค๋ฅธ ํ๋ก์ธ์ค์์๋ ์ด ๋งคํ๋ ์์ญ์ ๋ํ ์ฐธ์กฐ๊ฐ ์ ํจํ์ง ์๊ฒ ๋์ด๋ฒ๋ฆฐ๋ค. ๋ํ, ํ ๋งคํ์์ ํ์ผ์ ๋ด์ฉ์ ๋ณ๊ฒฝํ๋ฉด ๋ค๋ฅธ ๋งคํ์๋ ์ํฅ์ ์ฃผ๊ฒ ๋๋ค.
๊ทธ๋์ file_reopen ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ํ์ผ์ ๋ํ ์๋ก์ด fd๋ฅผ ์ป๊ฒ ๋์ด ๋ค๋ฅธ ๋งคํ์ ์ํฅ์ ์ฃผ๊ฑฐ๋ ์ํฅ์ ๋ฐ์ง ์๋ ๋ ๋ฆฝ์ ์ธ ๋งคํ์ ๊ฐ์ง ์ ์๊ฒ ๋๋ค.
void *
do_mmap (void *addr, size_t length, int writable,
struct file *file, off_t offset) {
struct file *re_file = file_reopen(file);
void *start_addr = addr; // ๋งคํ ์ฑ๊ณต ์ ํ์ผ์ด ๋งคํ๋ ๊ฐ์ ์ฃผ์ ๋ฐํํ๋ ๋ฐ ์ฌ์ฉ
size_t read_bytes = file_length(re_file) < length ? file_length(re_file) : length;
size_t zero_bytes = PGSIZE - read_bytes % PGSIZE;
ASSERT((read_bytes + zero_bytes) % PGSIZE == 0);
ASSERT(pg_ofs(addr) == 0); // upage๊ฐ ํ์ด์ง ์ ๋ ฌ๋์ด ์๋์ง ํ์ธ
ASSERT(offset % PGSIZE == 0); // ofs๊ฐ ํ์ด์ง ์ ๋ ฌ๋์ด ์๋์ง ํ์ธ
while (read_bytes > 0 || zero_bytes > 0)
{
size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
size_t page_zero_bytes = PGSIZE - page_read_bytes;
struct lazy_load_arg *lazy_load_arg = (struct lazy_load_arg *)malloc(sizeof(struct lazy_load_arg));
lazy_load_arg->file = re_file;
lazy_load_arg->ofs = offset;
lazy_load_arg->read_bytes = page_read_bytes;
lazy_load_arg->zero_bytes = page_zero_bytes;
// vm_alloc_page_with_initializer๋ฅผ ํธ์ถํ์ฌ ๋๊ธฐ ์ค์ธ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
if (!vm_alloc_page_with_initializer(VM_FILE, addr,
writable, lazy_load_segment, lazy_load_arg))
return NULL;
read_bytes -= page_read_bytes;
zero_bytes -= page_zero_bytes;
addr += PGSIZE;
offset += page_read_bytes;
}
return start_addr;
}
๐ซ์๋ฌ ๋ฌ๋ ์
struct file *re_file = file_reopen(file);
:
lazy_load_arg->file = re_file;
:
file_reopen(file)์ ํตํด ์๋ก ์ป์ fd๋ฅผ lazy_load_arg์ file๋ก ๋๊ฒผ์ด์ผ ํ๋๋ฐ ์ธ์๋ก ๋ฐ์๋ค์ธ file์ ๋๊ฒผ์ด์ ์๊พธ do_mmap()์์ ๋๋์ง ์๋ ์๋ฌ๊ฐ ๋ฌ์๋ค.
๊ผญ๊ผญ!! ์๋ก ์ป์ fd์ธ re_file์ ์ธ์๋ก ์ ์ฅํ๊ธฐ๋ฅผ ๋ฐ๋๋ค!!
์ด ์ดํ๋ก do_munmap()์ด ์๋๋ ๋ฌธ์ ๊ฐ ๊ณ์ํด์ ๋ฐ์ํ๋ค. ์ ๋ฅผ ์ฐ๋ค๊ฐ ๊ทธ ์ด์ ์ ๋ํด ์๊ฒ ๋์๋ค.
1. file_page ๊ตฌ์กฐ์ฒด ๋ฌธ์
struct file_page {
// struct file *file;
// off_t ofs;
// uint32_t read_bytes;
// uint32_t zero_bytes;
void* aux;
};
์ฃผ์ ์ฒ๋ฆฌ๋ ๊ฒ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก file_page์ ๋ณด์กฐ ๋ฐ์ดํฐ๋ค์ ์ ์ฅํด๋๋๋ฐ file ๊ตฌ์กฐ์ฒด ์์ file์ ์ ์ธํด๋๋ฉด ์๋๋ค๋ ๋๋ฃ๋ถ์ด file_page->aux๋ก ์ ๊ทผํด์ผ ํ๋ค๊ณ ํด์ ์์ ํ๋ค.
์ ํํ ์ด์ ๋ ์์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค ใ
๊ทธ๋์ ๊ด๋ จ๋ ์ฝ๋์ ๋ํด ์ ๋ถ ์์ ํด์ฃผ์๋ค.
file_backed_initalizer()
bool
file_backed_initializer (struct page *page, enum vm_type type, void *kva) {
/* Set up the handler */
page->operations = &file_ops;
struct file_page *file_page = &page->file;
file_page->aux = page->uninit.aux;
// struct lazy_load_arg *lazy_load_arg = (struct lazy_load_arg *)page->uninit.aux;
// file_page->file = lazy_load_arg->file;
// file_page->ofs = lazy_load_arg->ofs;
// file_page->read_bytes = lazy_load_arg->read_bytes;
// file_page->zero_bytes = lazy_load_arg->zero_bytes;
return true;
file_page ๊ตฌ์กฐ์ฒด์ ํฌ์ธํฐ๋ฅผ page->file๋ก ์ด๊ธฐํํ๊ณ , ํ์ด์ง์ ์ฐ๊ด๋ ๋ณด์กฐ ๋ฐ์ดํฐ๋ค์ file_page->aux์ ํ ๋นํ๋ค.
file_backed_destroy
file-backed ํ์ด์ง๋ ๋์คํฌ์ ์กด์ฌํ๋ ํ์ผ๊ณผ ์ฐ๊ด๋ ํ์ด์ง๋ค. ๊ทธ๋์ ๋ง์ฝ ํด๋น ํ์ด์ง์ ์์ ์ฌํญ์ด ์์ ๊ฒฝ์ฐ ์ด๋ฅผ ๊ฐ์งํ์ฌ ๋ณ๊ฒฝ์ฌํญ์ ๋์คํฌ์ ํ์ผ์ ์จ์ค์ผ ํ๋ค.
1. ํด๋น ํ์ด์ง๊ฐ ๋ณ๊ฒฝ๋์ด ์์ ๊ฒฝ์ฐ ๋์คํฌ์ ์กด์ฌํ๋ file์ write ํด์ฃผ๊ณ dirty-bit๋ฅผ ๋ค์ 0์ผ๋ก ๋ณ๊ฒฝ์์ผ์ค๋ค.
2. ๋ง์ฝ ๋ณ๊ฒฝ์ด ๋์ด ์์ง ์๋ค๋ฉด ํด๋น ํ์ด์ง๋ฅผ pml4์์ ์ญ์ ํด์ค๋ค.
static void
file_backed_destroy (struct page *page) {
struct file_page *file_page UNUSED = &page->file;
struct lazy_load_arg *file_aux = (struct lazy_load_arg *)file_page->aux;
struct thread *t = thread_current();
if(pml4_is_dirty(t->pml4, page->va)){
file_write_at(file_aux->file, page->va, file_aux->read_bytes, file_aux->ofs);
pml4_set_dirty(t->pml4, page->va, 0);
}
pml4_clear_page(t->pml4, page->va);
// if (pml4_is_dirty(thread_current()->pml4, page->va))
// {
// file_write_at(file_page->file, page->va, file_page->read_bytes, file_page->ofs);
// pml4_set_dirty(thread_current()->pml4, page->va, 0);
// }
// pml4_clear_page(thread_current()->pml4, page->va);
}
}
do_munmap()
์ฐ๊ฒฐ๋ ๋ฌผ๋ฆฌํ๋ ์๊ณผ์ ์ฐ๊ฒฐ์ ๋์ด์ค์ผ ํ๋ค.
์ฐ์ ์ฃผ์ด์ง addr์ ํตํด์ spt๋ก๋ถํฐ page๋ฅผ ํ๋ ์ฐพ๊ณ , ํด๋น ํ์ด์ง์ ๋ณด์กฐ ๋ฐ์ดํฐ๋ค์ page->file.aux์ ํ ๋นํ ํ์ file_backed_destroy()ํจ์๋ฅผ ํตํด ํ์ผ์ ์์ ์ฌํญ์ ๋ฐ์ํ๊ณ ๊ฐ์ ํ์ด์ง ๋ชฉ๋ก์์ ํ์ด์ง๋ฅผ ์ ๊ฑฐํ๋๋ก ํ๋ค.
void
do_munmap (void *addr) {
while(true){
struct thread *curr = thread_current();
struct page *find_page = spt_find_page(&curr->spt, addr);
if (find_page == NULL) {
return NULL;
}
struct lazy_load_arg* container = (struct lazy_load_arg*)find_page->uninit.aux;
find_page->file.aux = container;
file_backed_destroy(find_page);
addr += PGSIZE;
}
}
supplemental_page_table_copy()
์์ ํ๋ก์ธ์ค๊ฐ ๋ถ๋ชจ ํ๋ก์ธ์ค์ ์คํ ์ปจํ ์คํธ๋ฅผ ์์ํ๋ ๊ณผ์ ์์ spt๋ฅผ ๋ณต์ฌํ ๋, file_backed_page๋ ์์ ํ์ด์ง๊ฐ ๋ถ๋ชจ์ ํ๋ ์๊ณผ ๋งคํ๋๋๋ก ๋ถ๊ธฐ๋ฅผ ์ถ๊ฐํ๋ค.
bool supplemental_page_table_copy(struct supplemental_page_table *dst UNUSED,
struct supplemental_page_table *src UNUSED)
{
struct hash_iterator i;
hash_first(&i, &src->hash_table);
while (hash_next(&i))
{
struct page *src_page = hash_entry(hash_cur(&i), struct page, hash_elem);
enum vm_type vm_type = src_page->operations->type;
void *va = src_page->va;
bool writable = src_page->writable;
/* 1) type์ด uninit์ด๋ฉด */
if (vm_type == VM_UNINIT)
{ // uninit page ์์ฑ & ์ด๊ธฐํ
vm_initializer *init = src_page->uninit.init;
void *aux = src_page->uninit.aux;
vm_alloc_page_with_initializer(VM_ANON, va, writable, init, aux);
continue;
}
// if(vm_type == VM_FILE)
// {
// //ํ์ผ ๋ก๋ฉ์ ํ์ํ ์ ๋ณด ์ ์ฅ
// struct lazy_load_arg *file_aux =(struct lazy_load_arg *)malloc(sizeof(struct lazy_load_arg));
// file_aux->file = src_page->file.file;
// file_aux->ofs = src_page->file.ofs;
// file_aux->read_bytes = src_page->file.read_bytes;
// file_aux->zero_bytes = src_page->file.zero_bytes;
// //file_aux ๊ตฌ์กฐ์ฒด๋ฅผ ์ธ์๋ก ์ ๋ฌํ์ฌ VM_FILE page ์์ฑ & ์ด๊ธฐํ
// if(!vm_alloc_page_with_initializer(vm_type, va, writable, NULL, file_aux))
// return false;
// //์์ฑ๋ ํ์ด์ง ๊ฐ์ ธ์จ๋ค.
// struct page *file_page = spt_find_page(dst, va);
// //ํ์ผ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ ํ์ด์ง๋ฅผ ์ฑ์ด๋ค.
// file_backed_initializer(file_page, vm_type, va);
// //์์ฑ๋ ํ์ด์ง์ ํ๋ ์์ ์๋ณธ ํ์ด์ง์ ํ๋ ์์ผ๋ก ์ค์ ํ๋ค.
// file_page->frame = src_page->frame;
// //ํ์ด์ง ํ
์ด๋ธ์ ํ์ด์ง ๋งคํ
// pml4_set_page(thread_current()->pml4, file_page->va, src_page->frame->kva, src_page->writable);
// continue;
// }
else{
/* 2) type์ด uninit์ด ์๋๋ฉด */
if (!vm_alloc_page(vm_type, va, writable)) // uninit page ์์ฑ & ์ด๊ธฐํ
// init์ด๋ aux๋ Lazy Loading์ ํ์ํจ
// ์ง๊ธ ๋ง๋๋ ํ์ด์ง๋ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ฐ๋ก ๋ด์ฉ์ ๋ฃ์ด์ค ๊ฒ์ด๋ฏ๋ก ํ์ ์์
return false;
// vm_claim_page์ผ๋ก ์์ฒญํด์ ๋งคํ & ํ์ด์ง ํ์
์ ๋ง๊ฒ ์ด๊ธฐํ
if (!vm_claim_page(va))
return false;
// ๋งคํ๋ ํ๋ ์์ ๋ด์ฉ ๋ก๋ฉ
struct page *dst_page = spt_find_page(dst, va);
memcpy(dst_page->frame->kva, src_page->frame->kva, PGSIZE);
}
}
return true;
}