jun-wiki

View My GitHub Profile

Posts (Latest 10 updated) :
Read all
Contents:
  1. spt copy
    1. 순회
    2. UNINIT 복제 할때
    3. 실체 복제
    4. 실패 처리
    5. 헬퍼함수

10월이다

아직 정글이다


간단하게 spt copy 구현했다

spt copy

/* 보조 페이지 테이블을 src에서 dst로 복사한다. */
bool
supplemental_page_table_copy (struct supplemental_page_table *dst,
                              struct supplemental_page_table *src)
{
  struct hash_iterator it;
  hash_first(&it, &src->h);

  while (hash_next(&it)) {
    struct page *sp = hash_entry(hash_cur(&it), struct page, spt_elem);
    void *va = sp->va;
    bool writable = sp->writable;

    /* 현재 상태 */
    enum vm_type cur = VM_TYPE(sp->operations->type);

    if (cur == VM_UNINIT) {
      /* 초기화되면 어떤 타입이 될지 (ANON/FILE) */
      enum vm_type after = page_get_type(sp);
      vm_initializer *init = sp->uninit.init;

      void *aux_copy = NULL;
      if (VM_TYPE(after) == VM_FILE) {
        /* lazy_load_segment용 aux deep-copy (파일 핸들 duplicate) */
		/* 나중에는 file_reaopen()하고 file_close()로 대체 권장 */
        aux_copy = dup_aux_for_file_uninit(sp->uninit.aux);
        if (sp->uninit.aux && aux_copy == NULL) goto fail;
      } else {
        /* 보통 UNINIT(ANON)은 aux가 없거나 의미 없음 */
        aux_copy = NULL;
      }

      if (!vm_alloc_page_with_initializer(after, va, writable, init, aux_copy))
        goto fail;

      /* UNINIT은 여기서 끝. 자식은 첫 PF 때 로드됨. */
      continue;
    }

    /* 이미 메모리에 올라온 페이지(ANON 또는 FILE) → 자식에 ANON 생성 후 내용 복사 */
    if (!vm_alloc_page_with_initializer(VM_ANON, va, writable, NULL, NULL))
      goto fail;
    if (!vm_claim_page(va))
      goto fail;

    struct page *dp = spt_find_page(dst, va);
    if (dp == NULL || dp->frame == NULL) goto fail;

    /* 부모 페이지는 이미 메모리에 있어야 함 (swap 미구현 가정) */
    if (sp->frame == NULL) goto fail;

    memcpy(dp->frame->kva, sp->frame->kva, PGSIZE);
  }

  return true;

fail:
  /* 부분 생성된 dst 정리 */
  supplemental_page_table_kill(dst);
  return false;
}

대강 쪼개서 하는 일만 설명하겠다

순회

/* 보조 페이지 테이블을 src에서 dst로 복사한다. */
bool
supplemental_page_table_copy (struct supplemental_page_table *dst,
                              struct supplemental_page_table *src)
{
  struct hash_iterator it;
  hash_first(&it, &src->h);

  while (hash_next(&it)) {
    struct page *sp = hash_entry(hash_cur(&it), struct page, spt_elem);
    void *va = sp->va;
    bool writable = sp->writable;

    /* 현재 상태 */
    enum vm_type cur = VM_TYPE(sp->operations->type);

해시 테이블가지고 순회돌면서 현재 상태 (writable, VM_TYPE 등)를 기록하며 넘어간다

UNINIT 복제 할때

    if (cur == VM_UNINIT) {
      enum vm_type after = page_get_type(sp);     /* VM_ANON or VM_FILE */
      vm_initializer *init = sp->uninit.init;

      void *aux_copy = NULL;
      if (VM_TYPE(after) == VM_FILE) {
        aux_copy = dup_aux_for_file_uninit(sp->uninit.aux);
        if (sp->uninit.aux && aux_copy == NULL) goto fail;
      } else {
        aux_copy = NULL;
      }

페이지 폴트 났을때 어떤 타입으로 가져올지를 page_get_type을 통해 가져온다

타입이 FILE이면 aux도 필요하므로 깊은 복사 헬퍼 사용한다

타입이 ANON이면 aux가 보통 필요 없다

      if (!vm_alloc_page_with_initializer(after, va, writable, init, aux_copy))
        goto fail;

      continue;
    }

vm_alloc_page_with_initializer를 통해 자식 SPT에도 UNINIT 엔트리 생성한다

실체 복제

이미 부모가 메모리에 있을때(UNINIT 아닐때)다

    if (!vm_alloc_page_with_initializer(VM_ANON, va, writable, NULL, NULL))
      goto fail;
    if (!vm_claim_page(va))
      goto fail;

자식 SPT에서 새로운 ANON페이지 생성 후, 즉시 claim해 프레임 확보한다

FILE이어도 그냥 ANON으로 받게 했다

프로젝트2에는 CoW가 없기에 그냥 이렇게 처리하는게 더 좋다

    struct page *dp = spt_find_page(dst, va);
    if (dp == NULL || dp->frame == NULL) goto fail;

    if (sp->frame == NULL) goto fail;

    memcpy(dp->frame->kva, sp->frame->kva, PGSIZE);

만든 페이지와 프레임 검증한다

부모쪽도 있어야 하기에 이쪽도 같이 검증해준다

이후 부모 프레임에서 자식 프레임으로 복사한다

실패 처리

  }

  return true;

fail:
  supplemental_page_table_kill(dst);
  return false;
}

실패하면 어제 만든 kill 함수로 싹 날린다

헬퍼함수

static void *dup_aux_for_file_uninit(const void *aux0) {
  if (aux0 == NULL) return NULL;
  const struct load_aux *src = aux0;
  struct load_aux *dst = malloc(sizeof *dst);
  if (!dst) return NULL;
  *dst = *src;
  if (dst->file) {
    dst->file = file_duplicate(dst->file);
    if (!dst->file) { free(dst); return NULL; }
  }
  return dst;
}

별건 없고 NULL가드랑 타입 캐스팅, 메모리 할당 해준다

얕은 복사로 구조체 베껴오고 *dst = *src;

이후, file_duplicate를 통해 파일 핸들을 복사해온다