[운체] 오늘의 삽질 - 0806

방법이있지·2025년 8월 7일
post-thumbnail

fork 등에 필요

supplemental_page_table_copy

bool supplemental_page_table_copy(struct supplemental_page_table *dst UNUSED, struct supplemental_page_table *src UNUSED) {
    /* TODO: Iterate through each page in the src's supplemental page table and
   TODO: make a exact copy of the entry in the dst's supplemental page table.
   TODO: You will need to allocate uninit page and claim them immediately.
*/
}
  • __do_fork (fork 후 자식 프로세스쪽)에서 호출됨
  • SPT src에 저장된 모든 struct page 순회
  • 복사 후 SPT dst에 삽입하기
  • 삽입 후 곧바로 할당 요청 -> claim 해야 함.

해시테이블 요소 순회

  • 이러한 방식을 따름
struct hash_iterator i;
// h는 struct hash * 포인터
hash_first (&i, h);
while (hash_next (&i)) {
    struct page *p = hash_entry (hash_cur (&i), struct page, hash_elem);
    . . . do something with p . . .
}
  • 부모 spt의 각 엔트리 (struct page)에 대해,
    (1) 자식 spt에 삽입할 struct page 메모리 할당한다.
    (2) 부모 spt struct page의 필드 값을 직접 가져와서 초기화한다.
    (3) 자식 SPT에 struct page를 삽입한다.
    (4) 해당 struct page를 바로 claim한다.
    (5) 해당 struct page가 매핑된 경우, anon_initializer를 사용해서 claim한 후 부모 프레임을 memcpy한다.

supplemental_page_table_kill

  • process_exit()에서 호출됨
  • SPT의 모든 페이지에 destroy 호출
    • writeback (수정된 부분 갱신...)은 나중에 구현해도 될 것 같음
/* Free the resource hold by the supplemental page 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. */
}
  • 요소 순회하며, page에 destroy 호출 (destroy(page) 식) (앞선 do something with p 자리에)
  • destroy는 uninit page에선 uninit_destroy, anon page에선 anon_destroy를 호출
  • 두 함수는 별도로 정의하게 됨
  • cf. destroy를 호출해야 하는지, destroyfree를 둘 다 해주는 vm_dealloc_page를 호출해야 하는지... 일단 테케는 destroy만 해야 통과됐음.

page cleanup

  • struct page 필드의 메모리 할당 해제
  • struct page는 free하지 않음!!! 이건 uninit_destroy를 호출한 함수에서 free해야 함.

uninit_destroy

  • struct uninit_page 내 resource 메모리 할당 해제
/* Free the resources hold by uninit_page. Although most of pages are transmuted
 * to other page objects, it is possible to have uninit pages when the process
 * exit, which are never referenced during the execution.
 * PAGE will be freed by the caller. */
static void uninit_destroy(struct page *page) {
    struct uninit_page *uninit UNUSED = &page->uninit;
    /* TODO: Fill this function.
     * TODO: If you don't have anything to do, just return. */
}
struct uninit_page {
    /* Initiate the contets of the page */
    vm_initializer *init;
    enum vm_type type;
    void *aux;
    /* Initiate the struct page and maps the pa to the va */
    bool (*page_initializer)(struct page *, enum vm_type, void *kva);
};
  • init, page_initializer: 함수의 주소가 전달되므로 얘넬 free하면 안됨
  • aux: NULL이 아닌 경우 free?

anon_destroy

  • struct anon_page에 현재 정의한 필드가 없으므로, 현재는 할 수 있는 게 없음

exec (syscall.c)

  • exec는 기존 프로세스에 덮어씌워 새로운 프로그램 실행
  • 하지만 기존 SPT 테이블 정보가 남아 있어, process_exec -> load -> setup_stack 시도할 때 동일 주소에 이미 스택 있어 실패
  • process_exec 호출하기 전에 hash_clear로 SPT 테이블 초기화
// 3.5 process_exec로 덮어씌우기 전, SPT 테이블을 초기화
hash_clear(&(thread_current() -> spt.pages), NULL);

// 4. 안전하게 복사된 커널 포인터(cmd_line_copy)를 process_exec에 전달
if (process_exec(cmd_line_copy) == -1) {

    // process_exec은 성공하면 돌아오지 않으므로, 실패 시에만 종료
    exit(-1);
}
profile
뭔가 만드는 걸 좋아하는 개발자 지망생입니다. 프로야구단 LG 트윈스를 응원하고 있습니다.

1개의 댓글

comment-user-thumbnail
2025년 8월 7일

핀토 화이팅~ 스~~~

답글 달기