[Pintos-KAIST] Project 3 :: Anonymous Page (Lazy Loading์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ ๋†’์ด๊ธฐ)

2023. 5. 19. 11:27ใ†Computer Science

728x90
๋ฐ˜์‘ํ˜•

๐Ÿ’ก ์ด๋ฒˆ ํŒŒํŠธ์—์„œ๋Š” Anonymous page๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” non-disk based image๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

Anonymous Page๋ž€?
ํŒŒ์ผ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” file-backed page์™€ ๋‹ฌ๋ฆฌ, ์ด๋ฆ„์ด ์ง€์ •๋œ ํŒŒ์ผ ์†Œ์Šค๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— anonymous๋ผ๊ณ  ๋ถˆ๋ฆฌ๋ฉฐ,
 ์Šคํƒ๊ณผ ํž™ ์˜์—ญ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.

 

Lazy Loading์„ ์ด์šฉํ•œ ํŽ˜์ด์ง€ ์ดˆ๊ธฐํ™”

  • Lazy loading์€ ๋ฉ”๋ชจ๋ฆฌ ๋กœ๋”ฉ์„ ํ•„์š”ํ•œ ์‹œ์ ๊นŒ์ง€ ๋ฏธ๋ฃจ๋Š” ๋””์ž์ธ ํŒจํ„ด์ด๋‹ค.
  • Lazy Loading์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹นํ•  ๋•Œ ํ•ด๋‹น ํŽ˜์ด์ง€์— ๋Œ€์‘ํ•˜๋Š” page ๊ตฌ์กฐ์ฒด๋งŒ ๋งŒ๋“ค๊ณ , ๋ฌผ๋ฆฌ frame ํ• ๋‹น โŒ  ์‹ค์ œ ๋‚ด์šฉ๋„ โŒ (์•„์ง์€ ๋กœ๋”ฉํ•˜์ง€ ์•Š๋Š”๋‹ค!)
  • ๊ทธ๋Ÿผ ๋‚ด์šฉ์€ ์–ธ์ œ ๋กœ๋“œํ•˜์ง€ ?! ๐Ÿ‘‰๐Ÿป ์‹ค์ œ๋กœ ๋‚ด์šฉ์ด ๋กœ๋“œ๋˜๋Š” ์‹œ์ ์€ page fault๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์‹œ์ ์ด๋‹ค.
    page fault๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋Š” ๊ฒƒ์€ ์ด ์ฃผ์†Œ์— ์ ‘๊ทผํ–ˆ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , ์ ‘๊ทผํ–ˆ๋‹ค๋Š” ๊ฒƒ์€ ์‹ค์ œ๋กœ ๋‚ด์šฉ์ด ํ•„์š”ํ•œ ์‹œ์ ์ด ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
    ์ด page fault ์‹œ๊ทธ๋„์„ ๋ฐ›์•˜์„ ๋•Œ ๋‚ด์šฉ์ด ๋กœ๋“œ๋˜๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด Lazy Loading ์™„์„ฑ~!

 

๐Ÿค” ์ด๊ฑฐ ์™œ ํ•˜์ง€?

๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ์„ ์œ„ํ•ด์„œ!

Lazy loading์„ ์‚ฌ์šฉํ•˜๋ฉด ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ•„์š”ํ•œ ํŽ˜์ด์ง€๋ฅผ ํ•„์š”ํ•œ ์‹œ์ ์— ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์จ ๋ถˆํ•„์š”ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

 

Page initialization flow

ํŽ˜์ด์ง€๊ฐ€ ์ดˆ๊ธฐํ™”๋˜๋Š” ๊ณผ์ •์„ ๋จผ์ € ์‚ดํŽด๋ณด์ž.

  • uninit ํŽ˜์ด์ง€ ๊ตฌ์กฐ์ฒด ์ƒ์„ฑ : ์ปค๋„์ด ์ƒˆ๋กœ์šด ํŽ˜์ด์ง€ ์š”์ฒญ์„ ๋ฐ›์œผ๋ฉด vm_alloc_page_with_initializer ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
    • ์ด ํ•จ์ˆ˜๋Š” ํŽ˜์ด์ง€ ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด ๊ตฌ์กฐ์ฒด์— ํŽ˜์ด์ง€ ์œ ํ˜•์— ๋งž๋Š” ์ ์ ˆํ•œ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋“ค์„ ๋‹ด์•„๋‘”๋‹ค.
      (์ดˆ๊ธฐํ™”๋ฅผ ํ•˜์ง€๋Š” ์•Š๊ณ  ์ดˆ๊ธฐํ™”ํ•  ๋•Œ ์–ด๋–ค ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ๋‹ด์•„๋งŒ! ๋‘”๋‹ค.)
      ์ด๋ ‡๊ฒŒ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ์ƒํƒœ์˜ ํŽ˜์ด์ง€์˜ ํƒ€์ž…์€ VM๊ณผ uninitialized์˜ ์•ฝ์ž๋ฅผ ํ•ฉ์นœ VM_UNINIT์ด๋‹ค.
  • lazy loading์„ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋˜๋ฉด, ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋ฐ”์™€ ๊ฐ™์ด user ํ”„๋กœ๊ทธ๋žจ์ด ์ƒˆ ํŽ˜์ด์ง€์— ์ฒ˜์Œ ์ ‘๊ทผํ–ˆ์„ ๋•Œ page fault๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ๊ทธ ์ด์œ ๋Š”, ๋‚ด์šฉ์ด ์—†์„ ๋ฟ๋”๋Ÿฌ ํ• ๋‹น๋œ ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„๋„ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค!
  • page fault๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ ‘๊ทผํ•œ ๋ฉ”๋ชจ๋ฆฌ์˜ physical frame์ด ์กด์žฌํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ด ํ™•์ธ๋œ๋‹ค๋ฉด ์ด๋•Œ๊ฐ€ ๋ฐ”๋กœ loading์ด ํ•„์š”ํ•œ ์‹œ์ ์ด๋‹ค!
    ์ด๋•Œ ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์„ ํ• ๋‹นํ•˜๊ณ ๋‚˜์„œ uninit_initialize๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด์„œ ์•ž์„œ ์„ค์ •ํ•œ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋“ค์ด ํ˜ธ์ถœ๋˜์–ด ๋“œ๋””์–ด ์ดˆ๊ธฐํ™”๊ฐ€ ์ด๋ฃจ์–ด์ง„๋‹ค.
    • ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋Š” ์ต๋ช… ํŽ˜์ด์ง€์˜ ๊ฒฝ์šฐ anon_initializer, ํŒŒ์ผ ๊ธฐ๋ฐ˜ ํŽ˜์ด์ง€์˜ ๊ฒฝ์šฐ file_backed_initializer์ด๋‹ค.
    • ํŽ˜์ด์ง€ ๋ณ„ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜ ์™ธ์—๋„ lazy_load_segment ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉฐ ์ด ํ•จ์ˆ˜์—์„œ ๋‚ด์šฉ์ด ๋กœ๋“œ๋œ๋‹ค.

 

Lazy Loading for Executable

๐Ÿ’ก Implement vm_alloc_page_with_initializer().

1) vm_alloc_page_with_initializer

๐Ÿ”ฅ ๋ชฉํ‘œ: page ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ ์ ˆํ•œ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋ฅผ ์„ค์ •ํ•œ๋‹ค.

page ๊ตฌ์กฐ์ฒด ์ƒ์„ฑ

  • page ๊ตฌ์กฐ์ฒด๋ฅผ ํ•˜๋‚˜ ํ• ๋‹น๋ฐ›๋Š”๋‹ค.

uninit ํƒ€์ž…์œผ๋กœ ์ดˆ๊ธฐํ™” & ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜ ์„ค์ •

  • uninit_new ํ•จ์ˆ˜์˜ ์—ญํ• ์€ ์—ฌ๊ธฐ์„œ๋Š” uninit ํƒ€์ž…์œผ๋กœ ์ดˆ๊ธฐํ™”์‹œํ‚จ๋‹ค๊ณ ๋งŒ ์•Œ์•„๋‘๊ณ , ์•„๋ž˜์—์„œ ์ž์„ธํžˆ ์•Œ์•„๋ณผ ๊ฒƒ์ด๋‹ค!
  • ์ด page๋ฅผ uninit ํƒ€์ž…์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ ์œ„ํ•ด์„œ uninit_new ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š”๋ฐ,
    uninit_new ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ํ•„์š”ํ•œ ์ธ์ž๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.
    • p ์ดˆ๊ธฐํ™”ํ•  page ๊ตฌ์กฐ์ฒด
    • upage p๋ฅผ ํ• ๋‹นํ•  ๊ฐ€์ƒ ์ฃผ์†Œ
    • init p์˜ ๋‚ด์šฉ์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ํ•จ์ˆ˜
    • aux init์— ํ•„์š”ํ•œ ๋ณด์กฐ๊ฐ’
    • initializer p๋ฅผ ํƒ€์ž…์— ๋งž๊ฒŒ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ํ•จ์ˆ˜
  • ์ธ์ž ์ค‘์—์„œ p๋Š” ์œ„์—์„œ ํ• ๋‹น๋ฐ›์€ page ๊ตฌ์กฐ์ฒด๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋˜๊ณ , upage, init, aux๋Š” ์ผ๋‹จ vm_alloc_page_with_initializer๊ฐ€ ์ „๋‹ฌ ๋ฐ›์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์„ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•˜๋ฉด ๋œ๋‹ค. (์•„๋ž˜์—์„œ ์„ค๋ช…)
  • ๋งˆ์ง€๋ง‰ ์ธ์ž์ธ initializer๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋“ค์–ด์˜จ type์— ๋”ฐ๋ผ ๋ถ„๊ธฐ๊ฐ€ ํ•„์š”ํ•œ๋ฐ,
    1) anon ํƒ€์ž…์ด๋ฉด anon_initializer๋ฅผ, 2) file_backed ํƒ€์ž…์ด๋ฉด file_backed_initializer๋ฅผ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋กœ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค.
    • ์‹ค์ œ๋กœ C ์–ธ์–ด์—๋Š” "ํด๋ž˜์Šค"๋‚˜ "์ƒ์†"์ด ์—†์ง€๋งŒ, ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ "ํด๋ž˜์Šค ์ƒ์†" ๊ฐœ๋…์„ ๋„์ž…ํ•˜๊ธฐ ์œ„ํ•ด ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    • ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค๋Š” ๊ฒƒ์ด ์ƒ์†Œํ•˜๊ฒŒ ๋Š๊ปด์ง€๋Š”๋ฐ,
      uninit_new ํ•จ์ˆ˜์— ์„ ์–ธ๋˜์–ด ์žˆ๋Š” ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์˜ ํƒ€์ž…์ธ bool (*initializer)(struct page *, enum vm_type, void *) ์˜ ๋ฆฌํ„ด ํƒ€์ž…๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ํƒ€์ž…์ด ์ผ์น˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋œ๋‹ค.
    • initializer๋ผ๋Š” ์ด๋ฆ„์€ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์— ๋ถˆ๊ณผํ•˜๋ฏ€๋กœ ์ด๋ฆ„์€ ๋‹ฌ๋ผ์ ธ๋„ ์ƒ๊ด€ ์—†๋‹ค.
    • ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ ์ฃผ์†Œ๊ฐ’์„ ์ง€๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— & ๊ธฐํ˜ธ ์—†์ด ํ•จ์ˆ˜๋ช…๋งŒ ์ „๋‹ฌํ•˜๋ฉด ๋œ๋‹ค.
    • ์œ„ ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•ด๋‘๊ณ  ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ๊ฐ’์„ ๋ฐ”๊พธ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

page ๊ตฌ์กฐ์ฒด์˜ ํ•„๋“œ ์ˆ˜์ •

  • ๋งค๊ฐœ๋ณ€์ˆ˜ writable์„ page ๊ตฌ์กฐ์ฒด์˜ writable ํ•„๋“œ์— ํ• ๋‹นํ•œ๋‹ค.
    • (์ด๋ฅผ ์œ„ํ•ด ๋จผ์ € page ๊ตฌ์กฐ์ฒด์— writable ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.)
    • ํ•„๋“œ์˜ ๊ฐ’์„ ์ˆ˜์ •ํ•  ๋•Œ๋Š” uninit_new ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ ์ดํ›„์— ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค.
      Why? uninit_new ํ•จ์ˆ˜ ์•ˆ์—์„œ ๊ตฌ์กฐ์ฒด ๋‚ด์šฉ์ด ์ „๋ถ€ ์ƒˆ๋กœ ํ• ๋‹น๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. uninit_new ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ด์ „์—๋Š” ์•„๋ฌด๋ฆฌ ๊ฐ’์„ ์ถ”๊ฐ€ํ•ด๋„ ๋‹ค ๋‚ ๋ผ๊ฐ€๋‹ˆ ์ˆœ์„œ์— ์œ ์˜ํ•ด์•ผ ํ•œ๋‹ค!!!

page๋ฅผ SPT์— ์‚ฝ์ž…

  • page๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ page table์— ์ถ”๊ฐ€ํ•ด์•ผ๊ฒ ์ง€! ์ดˆ๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ๋œ page๋ฅผ ํ”„๋กœ์„ธ์Šค์˜ SPT์— ์‚ฝ์ž…ํ•˜๋ฉด ๋!

 

ํ•จ์ˆ˜ ๊ตฌํ˜„์„ ๋งˆ์ณค์œผ๋‹ˆ, ์ด์ œ๋ถ€ํ„ฐ๋Š” ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์ด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒ์„ฑํ•˜๋ฉด ๋œ๋‹ค.
(Lazy Loading์ด ํ•„์š” ์—†๋Š” ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” vm_alloc_page์„ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค.)

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)
    {
        /* TODO: Create the page, fetch the initialier according to the VM type,
         * TODO: and then create "uninit" page struct by calling uninit_new. You
         * TODO: should modify the field after calling the uninit_new. */
         
        // 1) ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ ,
        struct page *p = (struct page *)malloc(sizeof(struct page));
        
        // 2) type์— ๋”ฐ๋ผ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ์™€์„œ
        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;
        }

        // 3) "uninit" ํƒ€์ž…์˜ ํŽ˜์ด์ง€๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
        uninit_new(p, upage, init, type, aux, page_initializer);

        // ํ•„๋“œ ์ˆ˜์ •์€ uninit_new๋ฅผ ํ˜ธ์ถœํ•œ ์ดํ›„์— ํ•ด์•ผ ํ•œ๋‹ค.
        p->writable = writable;

        // 4) ์ƒ์„ฑํ•œ ํŽ˜์ด์ง€๋ฅผ SPT์— ์ถ”๊ฐ€ํ•œ๋‹ค.
        return spt_insert_page(spt, p);
    }
err:
    return false;
}

 

์œ„์—์„œ ์‚ฌ์šฉํ•œ uninit_new ํ•จ์ˆ˜์˜ ํ๋ฆ„์„ ๋”ฐ๋ผ๊ฐ€๋ณด์ž!

uninit_new ํ•จ์ˆ˜๊ฐ€ ํ•˜๋Š” ์ผ

  • uninit_new ํ•จ์ˆ˜์—์„œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ page ๊ตฌ์กฐ์ฒด๋ฅผ uninit type์œผ๋กœ ๋งŒ๋“ ๋‹ค.
    (page ๊ตฌ์กฐ์ฒด๋Š” uninit/anon/file/page_cache ์ค‘ ํ•œ๊ฐ€์ง€ ํƒ€์ž…์„ ๊ฐ€์ง€๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ๋Š” uninit ํƒ€์ž…์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฑฐ๋‹ˆ๊นŒ page ๊ตฌ์กฐ์ฒด์— uninit ํ•„๋“œ๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒƒ์ด๋‹ค.)
  • page->operations์—๋Š” uninit_ops๊ฐ€ ๋‹ด๊ธฐ๋Š”๋ฐ ์ด ๊ตฌ์กฐ์ฒด๋ฅผ ๋ณด๋ฉด swap_in์— uninit_initialize๊ฐ€ ๋‹ด๊ฒจ์žˆ๋‹ค.
    ํŽ˜์ด์ง€๊ฐ€ ์‹ค์ œ๋กœ ๋กœ๋”ฉ๋  ๋•Œ ์ด swap_in(์— ๋‹ด๊ธด uninit_initialize)๊ฐ€ ํ˜ธ์ถœ๋˜๊ฒŒ ๋˜๋ฉด์„œ (uninit ํŽ˜์ด์ง€์˜) ์ดˆ๊ธฐํ™”๊ฐ€ ์ด๋ฃจ์–ด์ง„๋‹ค.
    (uninit_initialize ์•ˆ์—์„œ ์ง€๊ธˆ ์„ค์ •ํ•˜๋Š” ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋“ค์ด ํ˜ธ์ถœ๋œ๋‹ค.)
    ๐Ÿ‘‡๐Ÿป uninit_ops ๊ตฌ์กฐ์ฒด
     
  • page->uninit->init์—๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ init์ด ๋‹ด๊ธฐ๋Š”๋ฐ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๋ณด๋ฉด process.c์˜ load_segment ํ•จ์ˆ˜์—์„œ vm_alloc_page_with_initializer๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ init ์ธ์ž๋กœ lazy_load_segment๋ฅผ ์ „๋‹ฌํ•œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
  • page->uninit->page_initializer์—๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ initializer๊ฐ€ ๋‹ด๊ธฐ๊ฒŒ ๋˜๋Š”๋ฐ, ์ง€๊ธˆ์€ ANON ํƒ€์ž…์˜ ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹นํ–ˆ์œผ๋ฏ€๋กœ anon_initializer๊ฐ€ ๋‹ด๊ธธ ๊ฒƒ์ด๋‹ค.
  • ํŽ˜์ด์ง€๊ฐ€ ์‹ค์ œ๋กœ ๋กœ๋”ฉ๋  ๋•Œ(์ฒซ๋ฒˆ์งธ page fault๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ) ํ˜ธ์ถœ๋˜๋Š” swap_in์€ page_fault์—์„œ ์ด์–ด์ง€๋Š” vm_do_claim_page ํ•จ์ˆ˜์—์„œ ํ˜ธ์ถœ๋˜๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
  • swap_in์— ๋‹ด๊ฒจ์žˆ๋˜ uninit_initialize์—์„œ๋Š” uninit->page_initializer์™€ uninit->init์ด ํ˜ธ์ถœ๋˜๋Š”๋ฐ, ์œ„์—์„œ ํ™•์ธํ•œ ๋ฐ”์™€ ๊ฐ™์ด
    uninit->page_initializer์—๋Š” anon_initializer, uninit->init์—๋Š” lazy_load_segment๊ฐ€ ๋‹ด๊ฒจ์žˆ์–ด ์ด ๋‘ ํ•จ์ˆ˜๊ฐ€ ๊ฐ๊ฐ ํ˜ธ์ถœ๋œ๋‹ค.
  • ์ •๋ฆฌํ•ด๋ณด๋ฉด, ์ฒซ๋ฒˆ์งธ page fault๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด์„œ
    vm_do_claim_page ํ•จ์ˆ˜์—์„œ ๋งคํ•‘์ด ์ด๋ฃจ์–ด์ง„ ์ดํ›„์— (swap_in์— ํ•ด๋‹นํ•˜๋Š”) uninit_initialize ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ ,
    ๊ทธ ์•ˆ์—์„œ ๊ฐ ํŽ˜์ด์ง€ ํƒ€์ž… ๋ณ„ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜์™€ ๋‚ด์šฉ์„ ๋กœ๋“œํ•˜๋Š” ํ•จ์ˆ˜(lazy_load_segment)๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

 

์ด์–ด์„œ ๋‚ด์šฉ์„ ๋กœ๋“œํ•˜๋Š” ํ•จ์ˆ˜์ธ load_segment์™€ lazy_load_segment๋ฅผ ์‚ดํŽด๋ณด์ž!

๐Ÿ’ก Implement load_segment and lazy_load_segment in userprog/process.c.

2) load_segment

  • ์ด ํ•จ์ˆ˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋  ๋•Œ ์‹คํ–‰ ํŒŒ์ผ์„ ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋กœ ๋กœ๋“œํ•˜๋Š” ํ•จ์ˆ˜์ธ load ํ•จ์ˆ˜์—์„œ ํ˜ธ์ถœ๋œ๋‹ค.
  • ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ upage์— ๋กœ๋“œํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
    ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด์„œ upage๋ฅผ ํ• ๋‹นํ•  page๊ฐ€ ํ•„์š”ํ•œ๋ฐ, ์œ„์—์„œ ์ˆ˜์ •ํ•œ vm_alloc_page_with_initializer ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์„œ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • Lazy Loading์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์—ฌ๊ธฐ์„œ ๋ฐ”๋กœ ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ๋กœ๋“œํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
    ๊ทธ๋ž˜์„œ page์— ๋‚ด์šฉ์„ ๋กœ๋“œํ•  ๋•Œ ์‚ฌ์šฉํ•  ํ•จ์ˆ˜์™€ ํ•„์š”ํ•œ ์ธ์ž๋“ค์„ ๋„ฃ์–ด์ค˜์•ผ ํ•˜๋Š”๋ฐ,
    vm_alloc_page_with_initializer ํ•จ์ˆ˜์˜ ๋„ค ๋ฒˆ์งธ, ๋‹ค์„ฏ ๋ฒˆ์งธ ์ธ์ž๊ฐ€ ๊ฐ๊ฐ ๋กœ๋“œํ•  ๋•Œ ์‚ฌ์šฉํ•  ํ•จ์ˆ˜, ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋•Œ ํ•„์š”ํ•œ ์ธ์ž์— ํ•ด๋‹นํ•œ๋‹ค.
  • ๋‚ด์šฉ์„ ๋กœ๋“œํ•  ๋•Œ ์‚ฌ์šฉํ•  ํ•จ์ˆ˜๋Š” lazy_load_segment๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ธ์ž๋Š” ์ง์ ‘ ๋งŒ๋“ค์–ด์„œ ๋„˜๊ฒจ์ฃผ์–ด์•ผ ํ•œ๋‹ค.
    lazy_load_segment์—์„œ ํ•„์š”ํ•œ(์ธ์ž๋กœ ๋„˜๊ฒจ์ค˜์•ผ ํ• ) ์ •๋ณด๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.
    • `file` ๋‚ด์šฉ์ด ๋‹ด๊ธด ํŒŒ์ผ ๊ฐ์ฒด 
    • `ofs` ์ด ํŽ˜์ด์ง€์—์„œ ์ฝ๊ธฐ ์‹œ์ž‘ํ•  ์œ„์น˜ 
    • `read_bytes` ์ด ํŽ˜์ด์ง€์—์„œ ์ฝ์–ด์•ผ ํ•˜๋Š” ๋ฐ”์ดํŠธ ์ˆ˜ 
    • `zero_bytes` ์ด ํŽ˜์ด์ง€์—์„œ read_bytes๋งŒํผ ์ฝ๊ณ  ๊ณต๊ฐ„์ด ๋‚จ์•„ 0์œผ๋กœ ์ฑ„์›Œ์•ผ ํ•˜๋Š” ๋ฐ”์ดํŠธ ์ˆ˜ 
    • lazy_load_arg๋ผ๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒˆ๋กœ ์ •์˜ํ•ด์„œ ์„ ์–ธํ•˜๊ณ  ์•ˆ์— ์œ„ ์ •๋ณด๋“ค์„ ๋‹ด์•„์„œ vm_alloc_page_with_initializer ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ์ธ์ž๋กœ ์ „๋‹ฌํ–ˆ๋‹ค.
  • ์ด์ œ page fault๊ฐ€ ์ฒ˜์Œ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, lazy_load_segment๊ฐ€ ์‹คํ–‰๋˜๊ณ  lazy_load_arg๊ฐ€ ์ธ์ž๋กœ ์‚ฌ์šฉ๋˜์–ด ๋‚ด์šฉ์ด ๋กœ๋”ฉ๋  ๊ฒƒ์ด๋‹ค.
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); // read_bytes + zero_bytes๊ฐ€ ํŽ˜์ด์ง€ ํฌ๊ธฐ(PGSIZE)์˜ ๋ฐฐ์ˆ˜์ธ์ง€ ํ™•์ธ
	ASSERT(pg_ofs(upage) == 0);						 // upage๊ฐ€ ํŽ˜์ด์ง€ ์ •๋ ฌ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
	ASSERT(ofs % PGSIZE == 0)						 // ofs๊ฐ€ ํŽ˜์ด์ง€ ์ •๋ ฌ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ;

	while (read_bytes > 0 || zero_bytes > 0) // read_bytes์™€ zero_bytes๊ฐ€ 0๋ณด๋‹ค ํฐ ๋™์•ˆ ๋ฃจํ”„๋ฅผ ์‹คํ–‰
	{
		/* Do calculate how to fill this page.
		 * We will read PAGE_READ_BYTES bytes from FILE
		 * and zero the final PAGE_ZERO_BYTES bytes. */
		// ์ด ํŽ˜์ด์ง€๋ฅผ ์ฑ„์šฐ๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ผ์—์„œ PAGE_READ_BYTES ๋งŒํผ ์ฝ๊ณ 	๋‚˜๋จธ์ง€ PAGE_ZERO_BYTES ๋งŒํผ 0์œผ๋กœ ์ฑ„์›๋‹ˆ๋‹ค.
		size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; // ์ตœ๋Œ€๋กœ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ํฌ๊ธฐ๋Š” PGSIZE
		size_t page_zero_bytes = PGSIZE - page_read_bytes;

		/* TODO: Set up aux to pass information to the lazy_load_segment. */
		// vm_alloc_page_with_initializer์— ์ œ๊ณตํ•  aux ์ธ์ˆ˜๋กœ ํ•„์š”ํ•œ ๋ณด์กฐ ๊ฐ’๋“ค์„ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
		// loading์„ ์œ„ํ•ด ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
		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; // ์ด ํŽ˜์ด์ง€์—์„œ read_bytes๋งŒํผ ์ฝ๊ณ  ๊ณต๊ฐ„์ด ๋‚จ์•„ 0์œผ๋กœ ์ฑ„์›Œ์•ผ ํ•˜๋Š” ๋ฐ”์ดํŠธ ์ˆ˜
		// vm_alloc_page_with_initializer๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋Œ€๊ธฐ ์ค‘์ธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
		if (!vm_alloc_page_with_initializer(VM_ANON, upage,
											writable, lazy_load_segment, lazy_load_arg))
			return false;

		/* Advance. */
		// ๋‹ค์Œ ๋ฐ˜๋ณต์„ ์œ„ํ•˜์—ฌ ์ฝ์–ด๋“ค์ธ ๋งŒํผ ๊ฐ’์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
		read_bytes -= page_read_bytes;
		zero_bytes -= page_zero_bytes;
		upage += PGSIZE;
		ofs += page_read_bytes;
	}
	return true;
}

3) lazy_load_segment

  • ์ด ํ•จ์ˆ˜๋Š” ์‹คํ–‰ ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ํŽ˜์ด์ง€๋กœ ๋กœ๋”ฉํ•˜๋Š” ํ•จ์ˆ˜์ด๋ฉฐ ์ฒซ๋ฒˆ์งธ page fault๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.
  • ์ด ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๊ธฐ ์ด์ „์— ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„ ๋งคํ•‘์ด ์ง„ํ–‰๋˜๋ฏ€๋กœ, ์—ฌ๊ธฐ์„œ๋Š” ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์— ๋‚ด์šฉ์„ ๋กœ๋”ฉํ•˜๋Š” ์ž‘์—…๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.
  • ์ด ํ•จ์ˆ˜๋Š” ํŽ˜์ด์ง€ ๊ตฌ์กฐ์ฒด์™€ aux๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š”๋‹ค.
    • aux๋Š” load_segment์—์„œ ๋กœ๋”ฉ์„ ์œ„ํ•ด ์„ค์ •ํ•ด๋‘” ์ •๋ณด์ธ lazy_load_arg์ด๋‹ค.
    • ์ด ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ์–ด์˜ฌ ํŒŒ์ผ์„ ์ฐพ์•„์„œ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋”ฉํ•œ๋‹ค.
bool lazy_load_segment(struct page *page, void *aux)
{
	/* TODO: Load the segment from the file */
	/* TODO: This called when the first page fault occurs on address VA. */
	/* TODO: VA is available when calling this function. */

	struct lazy_load_arg *lazy_load_arg = (struct lazy_load_arg *)aux;

	// 1) ํŒŒ์ผ์˜ position์„ ofs์œผ๋กœ ์ง€์ •ํ•œ๋‹ค.
	file_seek(lazy_load_arg->file, lazy_load_arg->ofs);
	// 2) ํŒŒ์ผ์„ read_bytes๋งŒํผ ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์— ์ฝ์–ด ๋“ค์ธ๋‹ค.
	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;
	}
	// 3) ๋‹ค ์ฝ์€ ์ง€์ ๋ถ€ํ„ฐ zero_bytes๋งŒํผ 0์œผ๋กœ ์ฑ„์šด๋‹ค.
	memset(page->frame->kva + lazy_load_arg->read_bytes, 0, lazy_load_arg->zero_bytes);

	return true;
}

4) setup_stack

  • ์ด ํ•จ์ˆ˜๋„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋  ๋•Œ load ํ•จ์ˆ˜ ์•ˆ์—์„œ ํ˜ธ์ถœ๋˜๋ฉฐ, STACK์˜ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
  • ์Šคํƒ์€ ์•„๋ž˜๋กœ ์„ฑ์žฅํ•˜๋ฏ€๋กœ, ์Šคํƒ์˜ ์‹œ์ž‘์ ์ธ USER_STACK์—์„œ PGSIZE๋งŒํผ ์•„๋ž˜๋กœ ๋‚ด๋ฆฐ ์ง€์ (stack_bottom)์—์„œ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • ์ฒซ ๋ฒˆ์งธ ์Šคํƒ ํŽ˜์ด์ง€๋Š” Lazy Loading์„ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋  ๋•Œ ์ด ํ•จ์ˆ˜๊ฐ€ ๋ถˆ๋ฆฌ๊ณ  ๋‚˜์„œ command line arguments๋ฅผ ์Šคํƒ์— ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ฃผ์†Œ์— ๋ฐ”๋กœ ์ ‘๊ทผํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
    ๋”ฐ๋ผ์„œ, ์ด ์ฃผ์†Œ์—์„œ fault๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ํ•„์š”์—†์ด ๋ฐ”๋กœ ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์„ ํ• ๋‹น๋ฐ›์•„ ๋†“๋Š”๋‹ค.
  • ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹น๋ฐ›์„ ๋•Œ ์ด ํŽ˜์ด์ง€๊ฐ€ ์Šคํƒ์˜ ํŽ˜์ด์ง€์ž„์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ณด์กฐ ๋งˆ์ปค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹น ๋ฐ›์„ ๋•Œ ํƒ€์ž…๊ณผ ํ•จ๊ป˜ VM_MARKER_0๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์Šคํƒ ํŽ˜์ด์ง€๋ฅผ ํ‘œ์‹œํ–ˆ๋‹ค. ๐Ÿ‘‰๐Ÿป ์Šคํƒ์—์„œ ํ• ๋‹น ๋ฐ›๋Š” ํŽ˜์ด์ง€์— ์ด ๋งˆ์ปค๋กœ ํ‘œ์‹œ๋ฅผ ํ•ด๋‘๋ฉด, ๋‚˜์ค‘์— ์ด ํŽ˜์ด์ง€๊ฐ€ ์Šคํƒ์˜ ํŽ˜์ด์ง€์ธ์ง€ ์•„๋‹Œ์ง€ ๋งˆ์ปค๋ฅผ ํ†ตํ•ด์„œ ์•Œ ์ˆ˜ ์žˆ์Œ!
  • ๋งˆ์ง€๋ง‰์œผ๋กœ, rsp ๊ฐ’์„ USER_STACK์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ค€๋‹ค. ์ด์ œ argument_stack ํ•จ์ˆ˜์—์„œ ์ด ์œ„์น˜(rsp)๋ถ€ํ„ฐ ์ธ์ž๋ฅผ pushํ•˜๊ฒŒ ๋œ๋‹ค.
static bool
setup_stack(struct intr_frame *if_)
{
	bool success = false;

	// ์Šคํƒ์€ ์•„๋ž˜๋กœ ์„ฑ์žฅํ•˜๋ฏ€๋กœ, USER_STACK์—์„œ PGSIZE๋งŒํผ ์•„๋ž˜๋กœ ๋‚ด๋ฆฐ ์ง€์ ์—์„œ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
	void *stack_bottom = (void *)(((uint8_t *)USER_STACK) - PGSIZE);

	/* TODO: Map the stack on stack_bottom and claim the page immediately.
	 * TODO: If success, set the rsp accordingly.
	 * TODO: You should mark the page is stack. */
	/* TODO: stack_bottom์— ์Šคํƒ์„ ๋งคํ•‘ํ•˜๊ณ  ํŽ˜์ด์ง€๋ฅผ ์ฆ‰์‹œ ์š”์ฒญํ•˜์„ธ์š”.
	 * TODO: ์„ฑ๊ณตํ•˜๋ฉด, rsp๋ฅผ ๊ทธ์— ๋งž๊ฒŒ ์„ค์ •ํ•˜์„ธ์š”.
	 * TODO: ํŽ˜์ด์ง€๊ฐ€ ์Šคํƒ์ž„์„ ํ‘œ์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. */
	/* TODO: Your code goes here */

	// 1) stack_bottom์— ํŽ˜์ด์ง€๋ฅผ ํ•˜๋‚˜ ํ• ๋‹น๋ฐ›๋Š”๋‹ค.
	if (vm_alloc_page(VM_ANON | VM_MARKER_0, stack_bottom, 1))
	// VM_MARKER_0: ์Šคํƒ์ด ์ €์žฅ๋œ ๋ฉ”๋ชจ๋ฆฌ ํŽ˜์ด์ง€์ž„์„ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€
	// writable: argument_stack()์—์„œ ๊ฐ’์„ ๋„ฃ์–ด์•ผ ํ•˜๋‹ˆ True
	{
		// 2) ํ• ๋‹น ๋ฐ›์€ ํŽ˜์ด์ง€์— ๋ฐ”๋กœ ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์„ ๋งคํ•‘ํ•œ๋‹ค.
		success = vm_claim_page(stack_bottom);
		if (success)
			// 3) rsp๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค. (argument_stack์—์„œ ์ด ์œ„์น˜๋ถ€ํ„ฐ ์ธ์ž๋ฅผ pushํ•œ๋‹ค.)
			if_->rsp = USER_STACK;
	}
	return success;
}

5) vm_try_handle_fault

  • ๋งˆ์ง€๋ง‰์œผ๋กœ, spt_find_page๋ฅผ ํ†ตํ•ด SPT๋ฅผ ์ฐธ์กฐํ•˜์—ฌ faulted address์— ํ•ด๋‹นํ•˜๋Š” ํŽ˜์ด์ง€ ๊ตฌ์กฐ์ฒด๋ฅผ ํ•ด๊ฒฐํ•˜๋„๋ก vm_try_handle_fault ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • page_fault๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ œ์–ด๊ถŒ์„ ์ „๋‹ฌ ๋ฐ›๋Š” ํ•จ์ˆ˜์ด๋‹ค.
  • ์ด ํ•จ์ˆ˜์—์„œ ํ• ๋‹น๋œ ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์•„์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ์ผ ๊ฒฝ์šฐ์—๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์ธ not_present์— true๋ฅผ ์ „๋‹ฌ๋ฐ›๋Š”๋‹ค.
    ๊ทธ๋Ÿด ๊ฒฝ์šฐ, SPT์—์„œ ํ•ด๋‹น ์ฃผ์†Œ์— ํ•ด๋‹นํ•˜๋Š” ํŽ˜์ด์ง€๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์„œ ์กด์žฌํ•œ๋‹ค๋ฉด ํ•ด๋‹น ํŽ˜์ด์ง€์— ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„ ํ• ๋‹น์„ ์š”์ฒญํ•˜๋Š” vm_do_claim_page ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
    ์ด ํ•จ์ˆ˜์—์„œ๋Š” ์œ„์—์„œ ์„ค์ •ํ•œ๋Œ€๋กœ ๊ฐ ํŽ˜์ด์ง€์— ๋งž๋Š” ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
  • not_present ๊ฐ’์ด false์ธ ์ƒํ™ฉ์„ ์‚ดํŽด๋ณด๋ฉด,
    ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์ด ํ• ๋‹น๋˜์–ด ์žˆ์ง€๋งŒ page fault๊ฐ€ ์ผ์–ด๋‚œ ๊ฒƒ์ด๋ฏ€๋กœ ๊ทธ ๊ฒฝ์šฐ๋Š” read-only page์— write๋ฅผ ํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋œ๋‹ค. ๋”ฐ๋ผ์„œ not_present๊ฐ€ false์ธ ๊ฒฝ์šฐ๋Š” ์˜ˆ์™ธ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋œ๋‹ค. (return false)
  • not_present๊ฐ€ true์ธ ๊ฒฝ์šฐ์—๋„, read-only page์— write ์š”์ฒญ์„ ํ•  ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ด์— ๋Œ€ํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
bool vm_try_handle_fault(struct intr_frame *f UNUSED, void *addr UNUSED,
                         bool user UNUSED, bool write UNUSED, bool not_present UNUSED)
{
    struct supplemental_page_table *spt UNUSED = &thread_current()->spt;
    struct page *page = NULL;
    if (addr == NULL)
        return false;

    if (is_kernel_vaddr(addr))
        return false;

    if (not_present) // ์ ‘๊ทผํ•œ ๋ฉ”๋ชจ๋ฆฌ์˜ physical page๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
    {
        /* TODO: Validate the fault */
        page = spt_find_page(spt, addr);
        if (page == NULL)
            return false;
        if (write == 1 && page->writable == 0) // write ๋ถˆ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€์— write ์š”์ฒญํ•œ ๊ฒฝ์šฐ
            return false;
        return vm_do_claim_page(page);
    }
    return false;
}

๐Ÿ’ก ์—ฌ๊ธฐ๊นŒ์ง€ ๊ตฌํ˜„ํ•˜๋ฉด fork๋ฅผ ์ œ์™ธํ•œ ํ”„๋กœ์ ํŠธ 2์˜ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผ๋œ๋‹ค!

  • Test ๊ฒฐ๊ณผ (55 of 141 tests failed.)
    pass tests/userprog/args-none
    pass tests/userprog/args-single
    pass tests/userprog/args-multiple
    pass tests/userprog/args-many
    pass tests/userprog/args-dbl-space
    pass tests/userprog/halt
    pass tests/userprog/exit
    pass tests/userprog/create-normal
    pass tests/userprog/create-empty
    pass tests/userprog/create-null
    pass tests/userprog/create-bad-ptr
    pass tests/userprog/create-long
    pass tests/userprog/create-exists
    pass tests/userprog/create-bound
    pass tests/userprog/open-normal
    pass tests/userprog/open-missing
    pass tests/userprog/open-boundary
    pass tests/userprog/open-empty
    pass tests/userprog/open-null
    pass tests/userprog/open-bad-ptr
    pass tests/userprog/open-twice
    pass tests/userprog/close-normal
    pass tests/userprog/close-twice
    pass tests/userprog/close-bad-fd
    pass tests/userprog/read-normal
    pass tests/userprog/read-bad-ptr
    pass tests/userprog/read-boundary
    pass tests/userprog/read-zero
    pass tests/userprog/read-stdout
    pass tests/userprog/read-bad-fd
    pass tests/userprog/write-normal
    pass tests/userprog/write-bad-ptr
    pass tests/userprog/write-boundary
    pass tests/userprog/write-zero
    pass tests/userprog/write-stdin
    pass tests/userprog/write-bad-fd
    FAIL tests/userprog/fork-once
    FAIL tests/userprog/fork-multiple
    FAIL tests/userprog/fork-recursive
    FAIL tests/userprog/fork-read
    FAIL tests/userprog/fork-close
    FAIL tests/userprog/fork-boundary
    pass tests/userprog/exec-once
    pass tests/userprog/exec-arg
    FAIL tests/userprog/exec-boundary
    pass tests/userprog/exec-missing
    pass tests/userprog/exec-bad-ptr
    FAIL tests/userprog/exec-read
    FAIL tests/userprog/wait-simple
    FAIL tests/userprog/wait-twice
    FAIL tests/userprog/wait-killed
    pass tests/userprog/wait-bad-pid
    FAIL tests/userprog/multi-recurse
    FAIL tests/userprog/multi-child-fd
    pass tests/userprog/rox-simple
    FAIL tests/userprog/rox-child
    FAIL tests/userprog/rox-multichild
    pass tests/userprog/bad-read
    pass tests/userprog/bad-write
    pass tests/userprog/bad-read2
    pass tests/userprog/bad-write2
    pass tests/userprog/bad-jump
    pass tests/userprog/bad-jump2
    FAIL tests/vm/pt-grow-stack
    pass tests/vm/pt-grow-bad
    FAIL tests/vm/pt-big-stk-obj
    pass tests/vm/pt-bad-addr
    pass tests/vm/pt-bad-read
    pass tests/vm/pt-write-code
    FAIL tests/vm/pt-write-code2
    FAIL tests/vm/pt-grow-stk-sc
    pass tests/vm/page-linear
    FAIL tests/vm/page-parallel
    FAIL tests/vm/page-merge-seq
    FAIL tests/vm/page-merge-par
    FAIL tests/vm/page-merge-stk
    FAIL tests/vm/page-merge-mm
    pass tests/vm/page-shuffle
    FAIL tests/vm/mmap-read
    FAIL tests/vm/mmap-close
    FAIL tests/vm/mmap-unmap
    FAIL tests/vm/mmap-overlap
    FAIL tests/vm/mmap-twice
    FAIL tests/vm/mmap-write
    pass tests/vm/mmap-ro
    FAIL tests/vm/mmap-exit
    FAIL tests/vm/mmap-shuffle
    FAIL tests/vm/mmap-bad-fd
    FAIL tests/vm/mmap-clean
    FAIL tests/vm/mmap-inherit
    FAIL tests/vm/mmap-misalign
    FAIL tests/vm/mmap-null
    FAIL tests/vm/mmap-over-code
    FAIL tests/vm/mmap-over-data
    FAIL tests/vm/mmap-over-stk
    FAIL tests/vm/mmap-remove
    pass tests/vm/mmap-zero
    FAIL tests/vm/mmap-bad-fd2
    FAIL tests/vm/mmap-bad-fd3
    FAIL tests/vm/mmap-zero-len
    FAIL tests/vm/mmap-off
    FAIL tests/vm/mmap-bad-off
    FAIL tests/vm/mmap-kernel
    FAIL tests/vm/lazy-file
    pass tests/vm/lazy-anon
    FAIL tests/vm/swap-file
    FAIL tests/vm/swap-anon
    FAIL tests/vm/swap-iter
    FAIL tests/vm/swap-fork
    pass tests/filesys/base/lg-create
    pass tests/filesys/base/lg-full
    pass tests/filesys/base/lg-random
    pass tests/filesys/base/lg-seq-block
    pass tests/filesys/base/lg-seq-random
    pass tests/filesys/base/sm-create
    pass tests/filesys/base/sm-full
    pass tests/filesys/base/sm-random
    pass tests/filesys/base/sm-seq-block
    pass tests/filesys/base/sm-seq-random
    FAIL tests/filesys/base/syn-read
    pass tests/filesys/base/syn-remove
    FAIL tests/filesys/base/syn-write
    pass tests/threads/alarm-single
    pass tests/threads/alarm-multiple
    pass tests/threads/alarm-simultaneous
    pass tests/threads/alarm-priority
    pass tests/threads/alarm-zero
    pass tests/threads/alarm-negative
    pass tests/threads/priority-change
    pass tests/threads/priority-donate-one
    pass tests/threads/priority-donate-multiple
    pass tests/threads/priority-donate-multiple2
    pass tests/threads/priority-donate-nest
    pass tests/threads/priority-donate-sema
    pass tests/threads/priority-donate-lower
    pass tests/threads/priority-fifo
    pass tests/threads/priority-preempt
    pass tests/threads/priority-sema
    pass tests/threads/priority-condvar
    pass tests/threads/priority-donate-chain
    FAIL tests/vm/cow/cow-simple
    55 of 141 tests failed.

 

Project2์˜ fork ๊ด€๋ จ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ์ด๋Š” ์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 

์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” __do_fork ํ•จ์ˆ˜์—์„œ supplemental_page_table_copy ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์–ด์„œ ์ด ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž!

 

Supplemental Page Table - Revisit

  • ์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ํ•„์š”ํ•œ SPT๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ํ•จ์ˆ˜์™€ ์ •๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

๐Ÿ’ก Implement supplemental_page_table_copy and supplemental_page_table_kill in vm/vm.c.

6) supplemental_page_table_copy

  • ์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์˜ SPT๋„ ์ž์‹์—๊ฒŒ ์ƒ์†ํ•ด์ค˜์•ผ ํ•˜๋Š”๋ฐ, ๊ทธ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
  • ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์˜ SPT์— ์žˆ๋Š” ๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ ๊ฐ ํƒ€์ž…์— ๋งž๊ฒŒ ํ• ๋‹น์„ ๋ฐ›๊ณ , uninit ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, ์ฆ‰ ๋‚ด์šฉ์ด ๋กœ๋”ฉ๋œ ์ƒํƒœ๋ผ๋ฉด ๋ฐ”๋กœ ๋งคํ•‘์„ ์ง„ํ–‰ํ•ด์„œ ๋‚ด์šฉ๊นŒ์ง€ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•œ๋‹ค.
  • file-backed page์ธ ๊ฒฝ์šฐ์—๋Š” ๋‹ค๋ฅธ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ anonymous page ํŒŒํŠธ์—์„œ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค. 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->spt_hash);
    while (hash_next(&i))
    {
        // src_page ์ •๋ณด
        struct page *src_page = hash_entry(hash_cur(&i), struct page, hash_elem);
        enum vm_type type = src_page->operations->type;
        void *upage = src_page->va;
        bool writable = src_page->writable;

        /* 1) type์ด uninit์ด๋ฉด */
        if (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, upage, writable, init, aux);
            continue;
        }

        /* 2) type์ด uninit์ด ์•„๋‹ˆ๋ฉด */
        if (!vm_alloc_page(type, upage, writable)) // uninit page ์ƒ์„ฑ & ์ดˆ๊ธฐํ™”
            // init์ด๋ž‘ aux๋Š” Lazy Loading์— ํ•„์š”ํ•จ
            // ์ง€๊ธˆ ๋งŒ๋“œ๋Š” ํŽ˜์ด์ง€๋Š” ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ๋‚ด์šฉ์„ ๋„ฃ์–ด์ค„ ๊ฒƒ์ด๋ฏ€๋กœ ํ•„์š” ์—†์Œ
            return false;

        // vm_claim_page์œผ๋กœ ์š”์ฒญํ•ด์„œ ๋งคํ•‘ & ํŽ˜์ด์ง€ ํƒ€์ž…์— ๋งž๊ฒŒ ์ดˆ๊ธฐํ™”
        if (!vm_claim_page(upage))
            return false;

        // ๋งคํ•‘๋œ ํ”„๋ ˆ์ž„์— ๋‚ด์šฉ ๋กœ๋”ฉ
        struct page *dst_page = spt_find_page(dst, upage);
        memcpy(dst_page->frame->kva, src_page->frame->kva, PGSIZE);
    }
    return true;
}

7) supplemental_page_table_kill

  • ์ด ํ•จ์ˆ˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ์™€ ์‹คํ–‰๋  ๋•Œ process_cleanup()์—์„œ ํ˜ธ์ถœ๋œ๋‹ค.
  • ํŽ˜์ด์ง€ ํ•ญ๋ชฉ๋“ค์„ ์ˆœํšŒํ•˜๋ฉฐ ํ…Œ์ด๋ธ” ๋‚ด์˜ ํŽ˜์ด์ง€๋“ค์˜ ํƒ€์ž…์— ๋งž๋Š” destroy ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
    • destroy ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŽ˜์ด์ง€ ํƒ€์ž…์— ๋”ฐ๋ผ์„œ uninit_destroy ํ˜น์€ anon_destroy ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
    • ํ• ๋‹น ๋ฐ›์€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ์—๋Š” ์ด ํŽ˜์ด์ง€๋กœ ์ธํ•ด ์œ ์ง€๋˜๋˜ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•ด์•ผ ํ•˜์ง€๋งŒ, ํ˜„์žฌ๋Š” ๋ณ„๋„๋กœ ํ• ๋‹น ๋ฐ›์€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์—†์–ด์„œ ๋น„์›Œ๋‘์—ˆ๋‹ค.
  • ์—ฌ๊ธฐ์„œ๋Š” hash table์€ ๋‘๊ณ  ์•ˆ์˜ ์š”์†Œ๋“ค๋งŒ ์ง€์›Œ์ค˜์•ผ ํ•œ๋‹ค.
    • hash_destroy ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด hash๊ฐ€ ์‚ฌ์šฉํ•˜๋˜ ๋ฉ”๋ชจ๋ฆฌ(hash->bucket) ์ž์ฒด๋„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ, hash_destroy๊ฐ€ ์•„๋‹Œ hash_clear๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
    • Why? process๊ฐ€ ์‹คํ–‰๋  ๋•Œ hash table์„ ์ƒ์„ฑํ•œ ์ดํ›„์— process_cleanup()์ด ํ˜ธ์ถœ๋˜๋Š”๋ฐ, ์ด๋•Œ๋Š” hash table์€ ๋‚จ๊ฒจ๋‘๊ณ  ์•ˆ์˜ ์š”์†Œ๋“ค๋งŒ ์ œ๊ฑฐ๋˜์–ด์•ผ ํ•œ๋‹ค.
      ๐Ÿ‘‰๐Ÿป hash table๊นŒ์ง€ ์ง€์›Œ๋ฒ„๋ฆฌ๋ฉด ๋งŒ๋“ค์ž๋งˆ์ž ์ง€์›Œ๋ฒ„๋ฆฌ๋Š” ๊ฒŒ ๋œ๋‹ค.. process๊ฐ€ ์‹คํ–‰๋  ๋•Œ ๋นˆ hash table์ด ์žˆ์–ด์•ผ ํ•˜๋ฏ€๋กœ hash table์€ ๋‚จ๊ฒจ๋‘๊ณ  ์•ˆ์˜ ์š”์†Œ๋“ค๋งŒ ์ง€์›Œ์•ผ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค!
void supplemental_page_table_kill(struct supplemental_page_table *spt UNUSED)
{
    /* TODO: Destroy all the supplemental_page_table hold by thread and
     * TODO: writeback all the modified contents to the storage. */
    hash_clear(&spt->spt_hash, hash_page_destroy); // ํ•ด์‹œ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ์š”์†Œ๋ฅผ ์ œ๊ฑฐ
}
void hash_page_destroy(struct hash_elem *e, void *aux)
{
    struct page *page = hash_entry(e, struct page, hash_elem);
    destroy(page);
    free(page);
}

 

 

๐Ÿ’ก ์ด์ œ ํ”„๋กœ์ ํŠธ 2์˜ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•œ๋‹ค. โœŒ๐Ÿป

  • Test ๊ฒฐ๊ณผ (36 of 141 tests failed.)
    pass tests/userprog/args-none
    pass tests/userprog/args-single
    pass tests/userprog/args-multiple
    pass tests/userprog/args-many
    pass tests/userprog/args-dbl-space
    pass tests/userprog/halt
    pass tests/userprog/exit
    pass tests/userprog/create-normal
    pass tests/userprog/create-empty
    pass tests/userprog/create-null
    pass tests/userprog/create-bad-ptr
    pass tests/userprog/create-long
    pass tests/userprog/create-exists
    pass tests/userprog/create-bound
    pass tests/userprog/open-normal
    pass tests/userprog/open-missing
    pass tests/userprog/open-boundary
    pass tests/userprog/open-empty
    pass tests/userprog/open-null
    pass tests/userprog/open-bad-ptr
    pass tests/userprog/open-twice
    pass tests/userprog/close-normal
    pass tests/userprog/close-twice
    pass tests/userprog/close-bad-fd
    pass tests/userprog/read-normal
    pass tests/userprog/read-bad-ptr
    pass tests/userprog/read-boundary
    pass tests/userprog/read-zero
    pass tests/userprog/read-stdout
    pass tests/userprog/read-bad-fd
    pass tests/userprog/write-normal
    pass tests/userprog/write-bad-ptr
    pass tests/userprog/write-boundary
    pass tests/userprog/write-zero
    pass tests/userprog/write-stdin
    pass tests/userprog/write-bad-fd
    pass tests/userprog/fork-once
    pass tests/userprog/fork-multiple
    pass tests/userprog/fork-recursive
    pass tests/userprog/fork-read
    pass tests/userprog/fork-close
    pass tests/userprog/fork-boundary
    pass tests/userprog/exec-once
    pass tests/userprog/exec-arg
    pass tests/userprog/exec-boundary
    pass tests/userprog/exec-missing
    pass tests/userprog/exec-bad-ptr
    pass tests/userprog/exec-read
    pass tests/userprog/wait-simple
    pass tests/userprog/wait-twice
    pass tests/userprog/wait-killed
    pass tests/userprog/wait-bad-pid
    pass tests/userprog/multi-recurse
    pass tests/userprog/multi-child-fd
    pass tests/userprog/rox-simple
    pass tests/userprog/rox-child
    pass tests/userprog/rox-multichild
    pass tests/userprog/bad-read
    pass tests/userprog/bad-write
    pass tests/userprog/bad-read2
    pass tests/userprog/bad-write2
    pass tests/userprog/bad-jump
    pass tests/userprog/bad-jump2
    FAIL tests/vm/pt-grow-stack
    pass tests/vm/pt-grow-bad
    FAIL tests/vm/pt-big-stk-obj
    pass tests/vm/pt-bad-addr
    pass tests/vm/pt-bad-read
    pass tests/vm/pt-write-code
    FAIL tests/vm/pt-write-code2
    FAIL tests/vm/pt-grow-stk-sc
    pass tests/vm/page-linear
    pass tests/vm/page-parallel
    pass tests/vm/page-merge-seq
    FAIL tests/vm/page-merge-par
    FAIL tests/vm/page-merge-stk
    FAIL tests/vm/page-merge-mm
    pass tests/vm/page-shuffle
    FAIL tests/vm/mmap-read
    FAIL tests/vm/mmap-close
    FAIL tests/vm/mmap-unmap
    FAIL tests/vm/mmap-overlap
    FAIL tests/vm/mmap-twice
    FAIL tests/vm/mmap-write
    pass tests/vm/mmap-ro
    FAIL tests/vm/mmap-exit
    FAIL tests/vm/mmap-shuffle
    FAIL tests/vm/mmap-bad-fd
    FAIL tests/vm/mmap-clean
    FAIL tests/vm/mmap-inherit
    FAIL tests/vm/mmap-misalign
    FAIL tests/vm/mmap-null
    FAIL tests/vm/mmap-over-code
    FAIL tests/vm/mmap-over-data
    FAIL tests/vm/mmap-over-stk
    FAIL tests/vm/mmap-remove
    pass tests/vm/mmap-zero
    FAIL tests/vm/mmap-bad-fd2
    FAIL tests/vm/mmap-bad-fd3
    FAIL tests/vm/mmap-zero-len
    FAIL tests/vm/mmap-off
    FAIL tests/vm/mmap-bad-off
    FAIL tests/vm/mmap-kernel
    FAIL tests/vm/lazy-file
    pass tests/vm/lazy-anon
    FAIL tests/vm/swap-file
    FAIL tests/vm/swap-anon
    FAIL tests/vm/swap-iter
    pass tests/vm/swap-fork
    pass tests/filesys/base/lg-create
    pass tests/filesys/base/lg-full
    pass tests/filesys/base/lg-random
    pass tests/filesys/base/lg-seq-block
    pass tests/filesys/base/lg-seq-random
    pass tests/filesys/base/sm-create
    pass tests/filesys/base/sm-full
    pass tests/filesys/base/sm-random
    pass tests/filesys/base/sm-seq-block
    pass tests/filesys/base/sm-seq-random
    pass tests/filesys/base/syn-read
    pass tests/filesys/base/syn-remove
    pass tests/filesys/base/syn-write
    pass tests/threads/alarm-single
    pass tests/threads/alarm-multiple
    pass tests/threads/alarm-simultaneous
    pass tests/threads/alarm-priority
    pass tests/threads/alarm-zero
    pass tests/threads/alarm-negative
    pass tests/threads/priority-change
    pass tests/threads/priority-donate-one
    pass tests/threads/priority-donate-multiple
    pass tests/threads/priority-donate-multiple2
    pass tests/threads/priority-donate-nest
    pass tests/threads/priority-donate-sema
    pass tests/threads/priority-donate-lower
    pass tests/threads/priority-fifo
    pass tests/threads/priority-preempt
    pass tests/threads/priority-sema
    pass tests/threads/priority-condvar
    pass tests/threads/priority-donate-chain
    FAIL tests/vm/cow/cow-simple
    36 of 141 tests failed.
728x90
๋ฐ˜์‘ํ˜•

'Computer Science' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Pintos-KAIST] Project 3 :: Memory Mapped Files  (2) 2023.05.22
[Pintos-KAIST] Project 3 :: Memory Management  (1) 2023.05.16
[Pintos-KAIST] Project 2 :: System Calls - 3 (File System), User Memory  (0) 2023.05.16