๐ฉ๐ปโ๐ป GITHUB ๋ ํฌ์งํ ๋ฆฌ
๐ฉ๐ปโ๐ป GITHUB Extend File Descriptor ์ด์
1๏ธโฃ ๋๋ฒ์งธ ๊ณผ์ ์ธ Anonymous Page๋ฅผ ์์ฑํ๊ธฐ ์ ๊น์ง VM ํ
์คํธ ์งํ์ด ๋ถ๊ฐํ๋ค. (threads๋ ๋์ด์ผํจ)
2๏ธโฃ .vscode/c_cpp_properties.json
defindes์ VM ์ถ๊ฐ
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"USERPROG",
"VM"
],
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
์ฝ๋ฐ์ฝ (์ฝ๋ ๋ฐ์ด ์ฝ๋... ๋ณธ์ธ ์ฝ๋์ ํด๋น ์๋๋๊ฑธ์๋ ์์)
3๏ธโฃ include/threads/thread.h
#define USERPROG ์ญ์
4๏ธโฃ threads/thread.c
#ifdef USERPROG ์ถ๊ฐ
ํ์ฌ ํํ ์ค์์๋ ๋ ๋ฒจ 4 ํ์ด์ง ํ ์ด๋ธ(pml4)์ ์ฌ์ฉํ์ฌ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ ๊ฐ์ ๋งคํ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ค. ํ์ง๋ง ์ด๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์๋ค. Supplemental Page Table์ ๊ตฌํํด ํ์ด์ง์ ๋ํ ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ค์ ์ ์ฅํ๊ฒ ๋๋ฉด Page Fault์ Resource Management๋ฅผ ์์ํ๊ฒ ์งํํ ์ ์๋ค.
supplemental page table์ ๊ธฐ์กด์ page table์ ๋ณด์ํ๊ธฐ ์ํด ๋ง๋ ๊ฒ์ด๋ค.
ํฌ๊ฒ ๋ ๊ฐ์ง ์ญํ ์ ์ํํ๋ค.
๋จผ์ ์ถ๊ฐ ํ์ด์ง ํ
์ด๋ธ์ ๊ตฌ์กฐ์ฒด struct supplemental_page_table
์ ๊ตฌํํ๋ค. ๊ทธ ํ์ ์ถ๊ฐ ํ
์ด๋ธ ๊ตฌ์กฐ์ฒด์ ๊ด๊ณ๋ ํจ์๋ฅผ ๊ตฌํํ๋ค.
Supplemental page table์ ๊ตฌํํ๋ ๋ฐฉ์์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ ์ ์๋ค. ๋ฐฐ์ด์ด๋, ๋นํธ๋งต, ํด์ ํ ์ด๋ธ๋ ๊ฐ๋ฅํ๋ค. hash table๋ก ๊ตฌํํ์.
frame table์ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ๋ด์ ๊ฐ ํ๋ ์์ ์ ๋ณด๋ฅผ ๊ฐ๊ณ ์๋ค.
Frame table์ frame entry์ ๋ฆฌ์คํธ๋ก ๊ตฌ์ฑ๋๋๋ฐ,
๊ฐ ์ํธ๋ฆฌ๋ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ํ๋ ์ ํ
์ด๋ธ๋ก ์ธํด eviction ์ ์ฑ
, ์ฆ SWAP OUT/IN์ ์ํ ํ๋ ์ ๊ต์ฒด ์ ์ฑ
์ ์ํํ ์ ์๊ฒ ๋๋ค.
#define VM_VM_H
#include <stdbool.h>
#include "threads/palloc.h"
#include <hash.h> /** Project 3-Memory Management */
...
struct supplemental_page_table {
struct hash spt_hash; /** Project 3-Memory Management */
};
struct page {
const struct page_operations *operations;
void *va; /* Address in terms of user space */
struct frame *frame; /* Back reference for frame */
/* Your implementation */
/* Per-type data are binded into the union.
* Each function automatically detects the current union */
union {
struct uninit_page uninit;
struct anon_page anon;
struct file_page file;
#ifdef EFILESYS
struct page_cache page_cache;
#endif
};
/** Project 3-Memory Management */
struct hash_elem hash_elem;
};
void
supplemental_page_table_init (struct supplemental_page_table *spt UNUSED) {
/** Project 3-Memory Management */
hash_init(spt, page_hash, page_less, NULL);
}
/** Project 3-Memory Management */
uint64_t page_hash(const struct hash_elem *e, void *aux);
/** Project 3-Memory Management */
uint64_t
page_hash(const struct hash_elem *e, void *aux)
{
struct page *page = hash_entry(e, struct page, hash_elem);
return hash_bytes(page->va, sizeof *page->va);
}
/** Project 3-Memory Management */
uint64_t page_hash(const struct hash_elem *e, void *aux);
bool page_less(const struct hash_elem *a, const struct hash_elem *b, void *aux);
/** Project 3-Memory Management */
bool
page_less(const struct hash_elem *a, const struct hash_elem *b, void *aux)
{
struct page *page_a = hash_entry(a, struct page, hash_elem);
struct page *page_b = hash_entry(b, struct page, hash_elem);
return page_a->va < page_b->va;
}
struct page *
spt_find_page (struct supplemental_page_table *spt UNUSED, void *va UNUSED) {
/** Project 3-Memory Management */
struct page *page = (struct page *)malloc(sizeof(struct page));
page->va = pg_round_down(va);
struct hash_elem *e = hash_find(&spt->spt_hash, &page->hash_elem);
free(page);
return e != NULL ? hash_entry(e, struct page, hash_elem) : NULL;
}
bool
spt_insert_page (struct supplemental_page_table *spt UNUSED,
struct page *page UNUSED) {
/** Project 3-Memory Management */
return hash_insert(&spt->spt_hash, &page->hash_elem) ? false : true;
}
/* vm.c: Generic interface for virtual memory objects. */
#include "threads/malloc.h"
#include "vm/vm.h"
#include "vm/inspect.h"
/** Project 3-Memory Management */
static struct list frame_table;
/* Initializes the virtual memory subsystem by invoking each subsystem's
* intialize codes. */
void
vm_init (void) {
vm_anon_init ();
vm_file_init ();
#ifdef EFILESYS /* For project 4 */
pagecache_init ();
#endif
register_inspect_intr ();
/* DO NOT MODIFY UPPER LINES. */
/** Project 3-Memory Management */
list_init(&frame_table);
}
struct frame {
void *kva;
struct page *page;
/** Project 3-Memory Management */
struct list_elem frame_elem;
};
static struct frame *
vm_get_frame (void) {
struct frame *frame = NULL;
/* TODO: Fill this function. */
/** Project 3-Memory Management */
struct frame *frame = (struct frame *)malloc(sizeof(struct frame));
ASSERT (frame != NULL);
frame->kva = palloc_get_page(PAL_USER | PAL_ZERO);
if (frame->kva == NULL)
frame = vm_evict_frame();
else
list_push_back(&frame_table, &frame->frame_elem);
frame->page = NULL;
ASSERT (frame->page == NULL);
return frame;
}
bool
vm_claim_page (void *va UNUSED) {
struct page *page = NULL;
/** Project 3-Memory Management */
struct page *page = spt_find_page(&thread_current()->spt, va);
if (page == NULL)
return false;
return vm_do_claim_page (page);
}
vm_get_frame()
ํจ์๋ฅผ ํตํด ํ๋ ์ ํ๋๋ฅผ ์ป๋๋ค.struct page {
const struct page_operations *operations;
void *va; /* Address in terms of user space */
struct frame *frame; /* Back reference for frame */
/* Your implementation */
/* Per-type data are binded into the union.
* Each function automatically detects the current union */
union {
struct uninit_page uninit;
struct anon_page anon;
struct file_page file;
#ifdef EFILESYS
struct page_cache page_cache;
#endif
};
/** Project 3-Memory Management */
struct hash_elem hash_elem;
bool writable;
};
/** Project 3-Memory Management */
#include "threads/mmu.h"
static struct list frame_table;
static bool
vm_do_claim_page (struct page *page) {
struct frame *frame = vm_get_frame ();
/* Set links */
frame->page = page;
page->frame = frame;
if (!pml4_set_page(thread_current()->pml4, page->va, frame->kva, page->writable))
return false;
return swap_in (page, frame->kva);
}