์ด๋ฒ ํํธ์์๋ Anonymous Page(non-disk based image)๋ฅผ ๊ตฌํํ๋ค.
Anonymous Page? ๐ค
์ต๋ช ๋งคํ์๋ ๋ฐฑ์ ํ์ผ์ด๋ ์ฅ์น๊ฐ ์๋ค. file-backed page์ ๋ฌ๋ฆฌ ์ด๋ฆ์ด ์๋ ํ์ผ ์์ค๋ฅผ ๊ฐ์ง๊ณ ์์ง ์๊ธฐ ๋๋ฌธ์ ์ต๋ช ์ด๋ผ๊ณ ํ๋ฉฐ, ์คํ ๊ฐ๋ฅํ ํ์ผ์์ ์คํ๊ณผ ํ ์์ญ์์ ์ฌ์ฉ๋๋ค.
= ์ด๋ค ํ์ผ๊ณผ๋ ๋งคํ๋์ง ์์ ๋ฉ๋ชจ๋ฆฌ ํ์ด์ง๋ก, ํ๋ก์ธ์ค์ ๋์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์์ฒญ์ ์๋ตํด ์์ฑ๋๋ค.
Lazy Loading์ด๋ ๋ฉ๋ชจ๋ฆฌ ๋ก๋ฉ์ ์ง์ฐ์์ผ ํ์ํ ์๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ฉํ๋ ๋์์ธ ํจํด์ด๋ค.
์ฆ, ํ์ด์ง๋ฅผ ํ ๋นํด ๋์ํ๋ ํ์ด์ง ๊ตฌ์กฐ์ฒด๋ ์์ผ๋ ๊ทธ๊ฒ๊ณผ ์ฐ๊ฒฐ๋ ๋ฌผ๋ฆฌ ํ๋ ์๊ณผ ํ์ด์ง์ ์ค์ ์ปจํ
์ธ ๋ ์์ง ๋ก๋๋์ง ์์ ์ํ๋ค. ์ด ์ํ์์ page fault๊ฐ ๋ฐ์ํ๋ฉด, ํด๋น ํ์ด์ง์ ๋ด์ฉ์ด ํ์ํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
์ด ๋ ํ์ด์ง์ ์ค์ ์ปจํ
์ธ ๋ฅผ ๋ก๋ํ๋ ๊ฒ Lazy Loading์ด๋ค.
Lazy Loading์ ํ๋ ์ด์ ๋? ๐ค
: ํ๋ก์ธ์ค๊ฐ ์ค์ ๋ก ์ฌ์ฉํ์ง ์๋ ํ์ด์ง๋ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋๋์ง ์๋๋ค. lazy loading์ ํ์ํ ์์ ์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํจ์ผ๋ก์จ ์์คํ ์ ๋ฆฌ์์ค ๋ญ๋น๋ฅผ ์ค์ด๊ณ , ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ณด๋ค ๋ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ํ๋ค.
PintOS์๋ 3๊ฐ์ง์ ํ์ด์ง ํ์
์ด ์๋๋ฐ, ๊ฐ ํ์
๋ณ ์ด๊ธฐํ ๋ฃจํด์ด ๋ค๋ฅด๋ค.
ํ์ด์ง์ ์ด๊ธฐํ ๊ณผ์ ์ด ์ด๋ป๊ฒ ๋๋์ง ์์๋ณด์.
vm_alloc_page_with_initializer()
์ปค๋์ด ์๋ก์ด ํ์ด์ง ์์ฒญ์ ๋ฐ์ผ๋ฉด vm_alloc_page_with_initializer()๋ฅผ ํธ์ถํ๋ค.
ํด๋น ํจ์๋ page ๊ตฌ์กฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ ์ ํ ์ด๊ธฐํ ํจ์๋ฅผ ์ค์ ํ๋ค. ๋ํ ์ด๋ ๊ฒ ์์ฑ๋ ํ์ด์ง๋ฅผ spt์ ์ถ๊ฐํ๋ค.
-> ์ด๊ธฐํํ์ง ์๊ณ ์ด๊ธฐํ ํจ์๋ฅผ '๋ด์๋ง' ๋๋๋ฐ, ์ด๋ ๊ฒ ์ด๊ธฐํ๋์ง ์์ ํ์ด์ง ํ์
์ uninit์ด๋ค.
page fault ๋ฐ์ -> vm_try_handle_fault - ...
์ ์ ํ๋ก๊ทธ๋จ์ด ์๋ก์ด ํ์ด์ง์ ์ฒ์ ์ ๊ทผํ๊ฒ ๋๋ฉด page fault๊ฐ ๋ฐ์๋๋ฉด์ lazy loading์ด ์ผ์ด๋๋ฉฐ, ์ด ๋ ๋ฌผ๋ฆฌ ํ๋ ์์ด ํ ๋น๋๋ฉด์ uninit page์ ๋ด๊ฒจ์๋ ์ด๊ธฐํ ํจ์๊ฐ ํธ์ถ๋๋ค.
ํ์ด์ง ์ด๊ธฐํ ๋ฐ lazy_load_segment
ํ์ด์ง ์ ํ์ ๋ง๋ ์ด๊ธฐํ ํจ์๊ฐ ํธ์ถ๋๊ณ , ๋์์ ๋ด์ฉ์ด ๋ก๋๋๋ค.
์ ๊ณผ์ ์ ํ๋ก ์ ๋ฆฌํ์๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
load_segment์์ while๋ฌธ์ผ๋ก vm_alloc_page_with_initializer๋ฅผ ํธ์ถํด ํ๋ก์ธ์ค๋ฅผ ํ์ด์ง ๋จ์๋ก ์ชผ๊ฐ๋ฉด์ spt์ ์ ์ฌํ๋ค.
vm_alloc_page_with_initializer์์๋ ์๋ก์ด ํ์ด์ง๋ฅผ ์์ฑํด type์ ๋ง๋ ์ด๊ธฐํ ํจ์๋ฅผ ๋ด์ ๋ค์ uninit_new๋ฅผ ํธ์ถํด uninit_page๋ก ์ด๊ธฐํ ํ๋ค.
1) vm_alloc_page_with_initializer()
page ๊ตฌ์กฐ์ฒด ์์ฑ ๋ฐ ์ ์ ํ ์ด๊ธฐํ ํจ์๋ฅผ ๋ด์ uninit ํ์ด์ง๋ก ์ด๊ธฐํ
bool vm_alloc_page_with_initializer(enum vm_type type, void *upage, bool writable,
vm_initializer *init, void *aux)
{
ASSERT(VM_TYPE(type) != VM_UNINIT)
struct supplemental_page_table *spt = &thread_current()->spt;
/* Check wheter the upage is already occupied or not. */
/* upage๊ฐ ์ด๋ฏธ ์ฌ์ฉ ์ค์ธ์ง ํ์ธ */
if (spt_find_page(spt, upage) == NULL)
{
/* ํ์ด์ง ์์ฑ */
struct page *p = (struct page *)malloc(sizeof(struct page));
/* ํ์ด์ง ํ์
์ ๋ฐ๋ผ ์ด๊ธฐํ ํจ์๋ฅผ ๊ฐ์ ธ์ ๋ด๊ธฐ */
bool (*page_initializer)(struct page *, enum vm_type, void *);
switch (VM_TYPE(type))
{
case VM_ANON:
page_initializer = anon_initializer;
break;
case VM_FILE:
page_initializer = file_backed_initializer;
break;
}
/* ์์ฑํ ํ์ด์ง๋ฅผ uninit page๋ก ์ด๊ธฐํ */
uninit_new(p, upage, init, type, aux, page_initializer);
/* ํ์ด์ง ๊ตฌ์กฐ์ฒด์ ํ๋ ์์ */
/* ํ๋ ๊ฐ์ ์์ ํ ๋ uninit ํธ์ถ ์ดํ์ ํด์ผ ํ๋ค = uninit_new ํจ์ ์์์ ๊ตฌ์กฐ์ฒด ๋ด์ฉ์ด ๋ชจ๋ ์๋ก ํ ๋น๋๊ธฐ ๋๋ฌธ์ */
p->writable = writable;
/* ์์ฑํ ํ์ด์ง spt์ ์ถ๊ฐ */
return spt_insert_page(spt, p);
}
err:
return false;
}
ํด๋น ํจ์์์ uninit_new()๋ฅผ ํธ์ถํด uninit page๋ก ์ด๊ธฐํํ๋๋ฐ, ์ด๋ป๊ฒ ์ด๊ธฐํํ ๊น?
void
uninit_new (struct page *page, void *va, vm_initializer *init,
enum vm_type type, void *aux,
bool (*initializer)(struct page *, enum vm_type, void *)) {
ASSERT (page != NULL);
*page = (struct page) {
.operations = &uninit_ops,
.va = va,
.frame = NULL, /* no frame for now */
.uninit = (struct uninit_page) {
.init = init,
.type = type,
.aux = aux,
.page_initializer = initializer,
}
};
}
page ๊ตฌ์กฐ์ฒด์ ๋ฉค๋ฒ๋ณ์๋ฅผ ํ ๋นํ๋ ๊ฒ ๊ฐ์๋ฐ, page ๊ตฌ์กฐ์ฒด๋ ์ด๋ป๊ฒ ๋ ๊น?
struct page
{
const struct page_operations *operations;
void *va; /* Address in terms of user space */
struct frame *frame; /* Back reference for frame */
/* Your implementation */
struct hash_elem bucket_elem; /* ํด์ ํ
์ด๋ธ ์์ */
bool writable;
/* 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
};
};
์ฌ๊ธฐ์ ์์ธํ ๋ด์ผํ ๊ฒ ๋ ๊ฐ์ง ์๋ค.
๐ค ํจ์ ํฌ์ธํฐ๋ ๋ญ๊น?
: ํจ์ ๋๋ ๋ฉ๋ชจ๋ฆฌ์ ์๋ ์คํ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ์ธ๋ฐ, ์ด๊ฑธ ์ ์ฐ๋ ๊ฑฐ์ง?
-> c์ธ์ด์์๋ ํด๋์ค์ ์์์ ๊ฐ๋ ์ด ์๋ค.
๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ํด๋์ค ์์์ ๋์ ํ๊ธฐ ์ํด ํจ์ ํฌ์ธํฐ๋ฅผ ์ ์ฉ์ํจ ๊ฒ์ด๋ค.
page_operations ๊ตฌ์กฐ์ฒด๋ฅผ ๋ณด๋ฉด swap_in, swap_out, destroy๊ฐ ์๋ ๊ฑธ ๋ณผ ์ ์์ ๊ฒ์ด๋ค.
ํ์ด์ง ์ ํ๋ง๋ค ๊ฐ ๋ฃจํด์ด ๋ค๋ฅผํ
๋, ํจ์ ํฌ์ธํฐ๋ฅผ ํ์ฉํด ํ์ด์ง ์ ํ์ ๋ง๋ ํจ์๋ฅผ ํธ์ถํ ๊ฒ์ด๋ค.
๋ค์์ผ๋ก union์ ๊ณต์ฉ์ฒด๋ก, ํ์ด์ง ์ ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ฉค๋ฒ ๋ณ์๋ฅผ ํฌํจํ๋ค.
๊ฐ ํ์ด์ง ์ ํ ๋ณ ํ์ํ ๋ฉค๋ฒ๋ณ์๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ด๋ค ๊ณต์ฉ์ฒด๋ฅผ ๊ฐ์ง๋์ ๋ฐ๋ผ ํ๋๊ฐ ์ถ๊ฐ๋๋ค.
์ด์ ํ์ด์ง์ ๊ตฌ์กฐ์ฒด๊น์ง ๋ดค์ผ๋ ๋ค์ uninit_new๋ก ๋์๊ฐ๋ณด์.
void
uninit_new (struct page *page, void *va, vm_initializer *init,
enum vm_type type, void *aux,
bool (*initializer)(struct page *, enum vm_type, void *)) {
ASSERT (page != NULL);
*page = (struct page) {
.operations = &uninit_ops,
.va = va,
.frame = NULL, /* no frame for now */
.uninit = (struct uninit_page) {
.init = init,
.type = type,
.aux = aux,
.page_initializer = initializer,
}
};
}
๋ค์ ๋ด๋ณด๋ page ๊ตฌ์กฐ์ฒด์ operations๋ฅผ uninit์ ๋ํ ์ฐ์ฐ์ ํ๋ &uninit_ops๋ก ํ ๋นํ๊ณ ,
union ๊ณต์ฉ์ฒด๋ฅผ uninit_page๋ก ๋ ์ผ๋ก์จ 4๊ฐ์ง์ ์ถ๊ฐ ๋ฉค๋ฒ๋ณ์๊ฐ ์์ฉํ๋ ๊ฑธ ์ ์ ์๋ค.
- init
: page์ ๋ด์ฉ์ ์ด๊ธฐํํ๋ ํจ์
= ์ด๋ vm_alloc_page_with_initializer์์ ์ธ์๋ก ๋ฐ์ lazy_load_segment๊ฐ ๋ค์ด๊ฐ ๊ฒ์ด๋ค.- type
: ํ์ด์ง ์ ํ
= ์ด๋ uninit์ด ์๋, ํ์ด์ง๋ฅผ ์์ฑํ ๋ ๋ด์ ์ ํ- aux
: init์ ํ์ํ ๋ณด์กฐ ์ธ์- initializer
: ํ์ด์ง ์ ํ์ ๋ฐ๋ฅธ ์ด๊ธฐํ ํจ์
= vm_alloc_page_with_initializer์์ ๋ด์ ์ด๊ธฐํ ํจ์
์ฌ๊ธฐ์ ์ฃผ์๊น๊ฒ ๋ด์ผํ ๊ฒ์ &uninit_ops์ init, ๊ทธ๋ฆฌ๊ณ initializer๋ค.
initializer
: ์ด๋ ๋งค๊ฐ๋ณ์๋ก ๋๊ฒจ์ฃผ๋ type์ ๋ฐ๋ผ ๋ค๋ฅธ ์ด๊ธฐํ ํจ์๋ฅผ ๋ด๊ฒ ๋๋ค.
vm_alloc_page_with_initializer์์ ์ธ์๋ก ๋ฐ์ type์ด anon type์ด๋ผ๋ฉด anon_initializer๊ฐ, file_backed type์ด๋ผ๋ฉด file_baced_initializer ํจ์ ํฌ์ธํฐ๋ฅผ ๋๊ฒจ์ค๋ค.
ํจ์ ์์ฒด๊ฐ ์ฃผ์๊ฐ์ ์ง๋๊ณ ์๊ธฐ ๋๋ฌธ์ ์ฃผ์๊ฐ ํํ๊ฐ ์๋ ํจ์๋ช
์์ฒด๋ฅผ ๋๊ฒจ์ค๋ค.
&uninit_ops
: page ๊ตฌ์กฐ์ฒด์ operations ๋ฉค๋ฒ๋ณ์๋ ํด๋น ํ์ด์ง์ ๋ํ ๋ค์ํ ์ฐ์ฐ์ ์ ์ํ๋ ํจ์ ํฌ์ธํฐ ๊ตฌ์กฐ์ฒด๋ผ๊ณ ํ์๋ค. uninit page์ ๋ํ ์ฐ์ฐ์ ์ด๋ป๊ฒ ์ด๋ค์ง๋์ง ํจ์ ํฌ์ธํฐ๋ฅผ ํ๊ณ ๋ค์ด๊ฐ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฑธ ๋ณผ ์ ์๋ค.
static const struct page_operations uninit_ops = {
.swap_in = uninit_initialize,
.swap_out = NULL,
.destroy = uninit_destroy,
.type = VM_UNINIT,
};
uninit page๋ฅผ swap_in ํ ๋ uninit_initialize ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
uninit_initialize ํจ์๋ฅผ ๋ด๋ณด์.
static bool
uninit_initialize (struct page *page, void *kva) {
struct uninit_page *uninit = &page->uninit;
/* Fetch first, page_initialize may overwrite the values */
vm_initializer *init = uninit->init;
void *aux = uninit->aux;
return uninit->page_initializer (page, uninit->type, kva) && (init ? init (page, aux) : true);
}
๋ฐํํ๋ ๊ฑธ ์ ๋ณด๋ฉด uninit page์ ๋ด๊ฒจ์๋ page_initializer๋ฅผ ํตํด ํ์ด์ง ํ์
์ ๋ง๊ฒ ์ด๊ธฐํํจ๊ณผ ๋์์ init์ ํธ์ถํ๋ ๊ฑธ ์ ์ ์๋ค. init์ ์์์ ๋งํ๋ค์ถ์ด lazy_load_segment์ธ๋ฐ, ์ด ํจ์๋ฅผ ํตํด ๋ฐ์ดํฐ ๋ก๋๊ฐ ์งํ๋๋ค.
๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ค๋ ๊ฒ์ ์ฒซ ๋ฒ์งธ page_fault๊ฐ ๋ฐ์ํ๋ค๋ ์๋ฏธ์ผ ๊ฒ์ด๋ค.
์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ ํจ์์ธ load_segment์ lazy_load_segment ํจ์๋ฅผ ๋ณผ ์ฐจ๋ก๋ค.
1) load_segment()
์์์ load_segment๊ฐ ์ ๊น ๋์๋๋ฐ, ํ๋ก์ธ์ค๋ฅผ ํ์ด์ง ๋จ์๋ก ์ชผ๊ฐ spt์ ์ ์ฌํ๋ค๊ณ ์ค๋ช
ํ์๋ค.
์์ธํ ์ค๋ช
ํ๋ฉด ํ์ผ์ ๋ด์ฉ์ ๋ก๋ํ๋ ํจ์์ธ๋ฐ, ๊ทธ ๋ด์ฉ์ ์ ์ฌํ page๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ vm_alloc_page_with_initializer๋ฅผ ํธ์ถํ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฐ๋ฐ ์ฐ๋ฆฌ๋ ๋ฐ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ์ง ์๊ธฐ๋ก ํ๋ค. lazy loading์ ํ๊ธฐ๋ก ํ๊ธฐ ๋๋ฌธ์ vm_alloc_page_with_initializer๋ฅผ ํธ์ถํ ๋ ์ธ์๋ก lazy_load_segment์ ๊ทธ๋ฅผ ์ํ ๋ณด์กฐ ์ธ์๋ค์ ๋ฃ์ด์ค์ผ ํ๋ค.
๋ณด์กฐ ์ธ์๋ค์ ํ์ฌ ๊ตฌํ๋์ด ์์ง ์๋ค. ์ฐ๋ฆฌ๊ฐ lazy_load_segment๋ฅผ ์ํด ํ์ํ ์ ๋ณด๋ค์ ์๊ฐํด ๊ทธ ์ ๋ณด๋ค์ ํฌํจํ ๊ตฌ์กฐ์ฒด๋ฅผ ๋ง๋ค์ด ๋๊ฒจ์ฃผ์ด์ผ ํ๋ค.
ํด๋น ์ ๋ณด๋ค์ ์ด๋ค๊ฒ ์์๊น?
- file: ํ์ผ ๋ด์ฉ์ด ๋ด๊ธด ํ์ผ ๊ฐ์ฒด
- ofs: ํ์ด์ง์์ ์ฝ๊ธฐ ์์ํ ์์น
- read_bytes: ํ์ด์ง์์ ์ฝ์ด์ผ ํ๋ ๋ฐ์ดํธ ์
- zero_bytes: ํ์ด์ง์์ read_bytes๋งํผ ์ฝ๊ณ , ๋จ์ ๊ณต๊ฐ์ 0์ผ๋ก ์ฑ์์ผ ํ๋ ๋ฐ์ดํธ ์
/* lazy_load_segment๋ฅผ ์ํ ๋ณด์กฐ ์ธ์๋ค */
struct lazy_load_arg
{
struct file *file; /* file ๋ด์ฉ์ด ๋ด๊ธด ํ์ผ ๊ฐ์ฒด */
off_t ofs; /* ํ์ด์ง์์ ์ฝ๊ธฐ ์์ํ ์์น */
uint32_t read_bytes; /* ํ์ด์ง์์ ์ฝ์ด์ผ ํ๋ ๋ฐ์ดํธ ์ */
uint32_t zero_bytes; /* ํ์ด์ง์์ read_bytes๋งํผ ์ฝ๊ณ ๋จ์ ๊ณต๊ฐ์ 0์ผ๋ก ์ฑ์์ผ ํ๋ ๋ฐ์ดํธ ์ */
};
์ด๋ฌํ ์ ๋ณด๋ฅผ ๋ด๊ธฐ ์ํ ๊ตฌ์กฐ์ฒด์ธ lazy_load_arg๋ฅผ ์ ์ธํ๊ณ load_segment์์ ํด๋น ์ ๋ณด๋ค์ ๋ด์ ๋ค ์ธ์๋ก ๋๊ฒจ์ฃผ์.
static bool
load_segment(struct file *file, off_t ofs, uint8_t *upage,
uint32_t read_bytes, uint32_t zero_bytes, bool writable)
{
ASSERT((read_bytes + zero_bytes) % PGSIZE == 0);
ASSERT(pg_ofs(upage) == 0);
ASSERT(ofs % PGSIZE == 0);
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;
/* lazy_load_segment์ ์ธ์๋ก ์ ๋ฌํด ์ค ๋ณด์กฐ ์ธ์๋ฅผ ๋ด์์ฃผ๊ธฐ */
struct lazy_load_arg *lazy_load_arg = (struct lazy_load_arg *)malloc(sizeof(struct lazy_load_arg));
lazy_load_arg->file = file;
lazy_load_arg->ofs = ofs;
lazy_load_arg->read_bytes = page_read_bytes;
lazy_load_arg->zero_bytes = page_zero_bytes;
if (!vm_alloc_page_with_initializer(VM_ANON, upage,
writable, lazy_load_segment, lazy_load_arg))
return false;
read_bytes -= page_read_bytes;
zero_bytes -= page_zero_bytes;
upage += PGSIZE;
ofs += page_read_bytes;
}
return true;
}
์ด๋ ๊ฒ ๋๋ฉด page fault๊ฐ ๋ฐ์ํ ๋ lazy_load_segment๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ๋ก๋๋ ๊ฒ์ด๋ค.
๊ทธ๋ผ ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ ํจ์์ธ lazy_load_segment๋ฅผ ๊ตฌํํด๋ณด์.
2) lazy_load_segment()
์ฒซ ๋ฒ์งธ page fault ๋ฐ์ ์, ํ์ด์ง ์ด๊ธฐํ์ ํจ๊ป ํธ์ถ๋๋ ํจ์๋ก ํ์ผ์ ๋ด์ฉ์ ํ์ด์ง๋ก ๋ก๋ํ๋ค.
ํด๋น ํจ์ ์ด์ ์ ํ์ด์ง์ ๋ฌผ๋ฆฌ ํ๋ ์์ ๋งคํ์ ์ด๋ฏธ ๋ค๋ฅธ ํจ์์์ ์ด๋ค์ง๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์์ ๋ฌผ๋ฆฌ ํ๋ ์์ ํ์ผ ๋ด์ฉ์ ๋ก๋ํ๊ธฐ๋ง ํ๋ค.
์ด์ ์ lazy_load_segment๋ฅผ ์ํ ๋ณด์กฐ ์ธ์๋ค์ ๋ฐ์์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ํ์ฉํด ์ฝ์ด์ฌ ํ์ผ์ ๋ํด ๋ด์ฉ์ ๋ก๋ํ๋๋ก ๊ตฌํํ๋ฉด ๋๋ค.
bool lazy_load_segment(struct page *page, void *aux)
{
struct lazy_load_arg *lazy_load_arg = (struct lazy_load_arg *)aux;
/* file์ offset์ lazy_load_arg์ ofs์ผ๋ก ์ด๋์ํด(์ฝ๊ธฐ ์์ํ ์์น) */
file_seek(lazy_load_arg->file, lazy_load_arg->ofs);
/* ํ์ด์ง์ ๋งคํ๋ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์ ํ๋ ์์ ์ด๋์ํจ ofs์์๋ถํฐ ํ์ผ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ด */
/* ์ ๋๋ก ์ฝ์ด์ค์ง ๋ชป ํ๋ค๋ฉด -> ํด๋น ํ์ด์ง๋ฅผ Free ์ํค๊ณ False ๋ฐํ */
if (file_read(lazy_load_arg->file, page->frame->kva, lazy_load_arg->read_bytes) != (int)(lazy_load_arg->read_bytes))
{
palloc_free_page(page->frame->kva);
return false;
}
/* ๋จ๋ ๋ถ๋ถ์ 0์ผ๋ก ์ด๊ธฐํ */
memset(page->frame->kva + lazy_load_arg->read_bytes, 0, lazy_load_arg->zero_bytes);
return true;
}
์ด๋ ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ ๋ถ๋ถ๊น์ง ๊ตฌํํ์ง๋ง, ์ฌ์ค ์์ง ์ ์ฒด์ ์ธ ๊ทธ๋ฆผ์ด ๊ทธ๋ ค์ง์ง ์์๋ค.
๊ทธ๋์ ๊ฐ ํจ์๋ค์ด ์ด๋์ ํธ์ถ๋๊ณ , ์ฐ๊ฒฐ๋๋์ง ํ์์ ๋์์ ๋ฐ์ ๋ค์๊ณผ ๊ฐ์ด ์ ๋ฆฌ๋ฅผ ํด๋ดค๋ค.
๊ทธ๋ฐ๋ฐ ์ฐ๋ฆฌ๊ฐ ์ง๊ธ๊น์ง ๋ค๋ฃจ์ง ์์ ๋ถ๋ถ์ด ๋ณด์ผ ๊ฒ์ด๋ค. setup_stack()?
ํ๋ก์ธ์ค๋ฅผ ๋ก๋ฉํ ๋, ์ฆ ์คํํ ๋ load ํจ์์์ ํธ์ถ๋๋ ํจ์๋ก ํ ๋ฒ๋ง ํธ์ถ๋๋ค.
setup_stack()์ stack์ ์ด๊ธฐ ํ์ด์ง๋ฅผ ์์ฑํ๋ค.
์ด ๋ง์, ์ฒซ ๋ฒ์งธ ์คํ ํ์ด์ง๋ฅผ Lazy Loading์ผ๋ก ๋ก๋ํ ํ์๊ฐ ์๋ค. ์ด์ฐจํผ ํ๋ก์ธ์ค๊ฐ ์คํ๋ ๋ setup_stack()์ ํธ์ถํ๊ณ ๋์ ์ปค๋งจ๋ ๋ผ์ธ์ ์ธ์๋ค ์คํ์ ์ ์ฅํ๊ธฐ ์ํด ํด๋น ์ฃผ์์ ๋ฐ๋ก ์ ๊ทผํ๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ฌ๋๊น page fault๊ฐ ๋ฐ์ํ๊ณ lazy loadingํ๊ธธ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ฐ๋ก ๋ฌผ๋ฆฌ ํ๋ ์์ ํ ๋น ๋ฐ์ ํ์ด์ง์ ๋งคํํด์ค๋ค.
์ฃผ์ํ ์ : ์คํ์ ์๋๋ก ์ฑ์ฅํ๊ธฐ ๋๋ฌธ์ ์คํ์ ์์์ (USER_STACK)์์ PGSIZE๋งํผ '์๋'๋ก ๋ด๋ฆฐ ์ง์ ์์ ์์ฑํ๋ค.
๋ํ ํ์ด์ง๋ฅผ ํ ๋น๋ฐ์ ๋ ํด๋น ํ์ด์ง๊ฐ ์คํ์ ํ์ด์ง์์ ํ์ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ณด์กฐ ๋ง์ปค๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ํ์ด์ง๋ฅผ ํ ๋น ๋ฐ์ ๋ ํ์ด์ง์ ํ์
๊ณผ ํจ๊ป VM_MARKER_0์ ์ฌ์ฉํด ํ์ํ ์ ์๋ค.
๋์ค์ ์ด ๋ง์ปค๋ฅผ ํตํด ์คํ์ ํ์ด์ง์ธ์ง ์ ์ ์๋ค.
ํ ๋น๋ฐ์ ํ์ด์ง์ ๋ฌผ๋ฆฌ ํ๋ ์์ ๋งคํํ๋๋ฐ ์ฑ๊ณตํ๋ค๋ฉด ์คํ ํฌ์ธํฐ(rsp)๋ฅผ USER_STACK์ผ๋ก ์ค์ ํ๋ค.
์์ผ๋ก ์ด rsp๋ถํฐ ์ธ์๋ค์ pushํ๊ฒ ๋ ๊ฒ์ด๋ค.
/* ํ๋ก์ธ์ค๊ฐ ์คํ๋ ๋ load()์์ ํธ์ถ, STACK์ ํ์ด์ง๋ฅผ ์์ฑํ๋ ํจ์ */
static bool
setup_stack(struct intr_frame *if_)
{
bool success = false;
/* ์คํ์ ์๋๋ก ์ปค์ง๋๊น, ์คํ ์์์ USER_STACK์์ PGSIZE๋งํผ ์๋๋ก ๋ด๋ ค๊ฐ ์ง์ ์์ ํ์ด์ง ์์ฑ = stack_bottom */
void *stack_bottom = (void *)(((uint8_t *)USER_STACK) - PGSIZE);
/* stack_bottm์ ์คํ ๋งคํ ํ ํ์ด์ง ์์ฒญ */
/* ์ฑ๊ณต ์, rsp๋ฅผ ๊ทธ์ ๋ง๊ฒ ์ค์ */
/* ๋ํ ํ์ด์ง๊ฐ ์คํ์ ์์์ ํ์ํด์ผ ํจ */
/* stack_bottom์ ํ์ด์ง ํ ๋น ๋ฐ์ (์คํ์ ์๋๋ก ์ปค์ง๋๊น) */
/* VM_MARKER_0: ์คํ์ด ์ ์ฅ๋ ๋ฉ๋ชจ๋ฆฌ ํ์ด์ง ์๋ณ */
if (vm_alloc_page(VM_ANON | VM_MARKER_0, stack_bottom, 1))
{
/* ํ ๋น๋ฐ์ ํ์ด์ง์ ๋ฌผ๋ฆฌ ํ๋ ์ ๋งคํ */
success = vm_claim_page(stack_bottom);
if (success)
{
/* rsp ๋ณ๊ฒฝ */
if_->rsp = USER_STACK;
thread_current()->stack_bottom = stack_bottom;
}
}
return success;
}
์ฌ๊ธฐ๊น์ง lazy loading์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํจ์ผ๋ก์จ page fault๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๊ตฌํํ๋ค.
์ด์ page fault๊ฐ ๋ฐ์ํ์ ๋ ์ง๊ธ๊น์ง ๊ตฌํํ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋๋ก handler๋ฅผ ์์ ํด์ผ ํ๋ค.
ํด๋น ๋ถ๋ถ๋ถํฐ๋ ๋ค์ ๊ธ์์ ์ ๋ฆฌํด์ผ๊ฒ ๋ค.