[SW정글][핀토스] 0. 깃북 정리 - Memory Management

JST·2023년 10월 12일
0

핀토스 VM

목록 보기
4/5

Memory Management

임의의 가상 / 물리 메모리 영역을 누가 사용했고, 어떤 목적으로 사용했는지 등을 다뤄야 함.
1. supplemental page table
2. 물리메모리 페이지 프레임

페이지 구조체

include/vm/vm.h에 정의되어 있는 page는 가상 메모리에서의 페이지를 의미하는 구조체입니다.
이 구조체는 page에 대해 우리가 알아야 하는 모든 필요한 정보를 담고 있습니다. 이 구조체는 아래와 같이 구현되어 있습니다.

struct page {
  const struct page_operations *operations;
  void *va;              /* Address in terms of user space */
  struct frame *frame;   /* Back reference for frame */

  union {
    struct uninit_page uninit;
    struct anon_page anon;
    struct file_page file;
#ifdef EFILESYS
    struct page_cache page_cache;
#endif
  };
};

union

이 구조체는 union 멤버도 가지고 있다.
union 자료형은 하나의 메모리 영역에 다른 타입의 데이터를 저장하는 것을 허용하는 특별한 자료형이다.
(즉, array같은 한 자료형만 저장 가능한 것과는 반대로 struct처럼 여러 자료형을 저장할 수 있다.
하지만 차이가 있다면 struct와는 달리 union은 크기가 가장 큰 멤버의 크기만큼을 할당받아 멤버들이 그 메모리를 공유한다. 즉, 한 번에 멤버 중 하나만이 그 공간을 사용하게 된다.)
따라서 우리 시스템에서 페이지는 uninit_page이거나, anon_page 이거나, file_page이거나, page_cache일 수 있다.
예를 들어 페이지가 익명 페이지라면, 페이지 구조체는 struct anon_page anon 을 멤버 중 하나로 가지고 있을 것이다. anon_page 은 익명 페이지를 위해 우리가 기억해야 하는 필수적인 정보들을 담고 있을 것이다.

page_operations

한 페이지는 VM_UNINIT , VM_ANON , VM_FILE 라는 세 가지 종류 중 하나이며, 각 페이지는 서로 다른 destroy 함수를 호출합니다. 이를 위해 switch-case 구문을 활용해서 각 케이스에 맞는 함수를 사용하는 방법이 하나 있습니다. 이는 클래스 상속과 유사한 개념이며, 우리는 이 개념을 이해하기 위해 함수 포인터를 사용할 것입니다.

우리의 케이스에서는 코드레벨에서 destroy (page) 라는 함수를 호출하는 것만으로 충분합니다. 그러면 컴파일러는 올바른 함수 포인터를 호출하여, 페이지 타입에 따라 적절한 destroy 루틴을 선택할 것입니다.

page_operations 구조체

이 구조체는 3개의 함수 포인터를 포함한 하나의 함수 테이블로 이해해라

struct page_operations {
  bool (*swap_in) (struct page *, void *);
  bool (*swap_out) (struct page *);
  void (*destroy) (struct page *);
  enum vm_type type;
};

Implement Supplemental Page Table

보충 테이블 페이지에서 구현할 함수 3가지
1.

void supplemental_page_table_init (struct supplemental_page_table *spt);

위의 함수는 보조 페이지 테이블를 초기화합니다. 보조 페이지 테이블를 어떤 자료 구조로 구현할지 선택하세요. userprog/process.c의 initd 함수로 새로운 프로세스가 시작하거나 process.c의 __do_fork로 자식 프로세스가 생성될 때 위의 함수가 호출됩니다.

struct page *spt_find_page (struct supplemental_page_table *spt, void *va);

위의 함수는 인자로 넘겨진 보조 페이지 테이블에서로부터 가상 주소(va)와 대응되는 페이지 구조체를 찾아서 반환합니다. 실패했을 경우 NULL를 반환합니다.

bool spt_insert_page (struct supplemental_page_table *spt, struct page *page);

위의 함수는 인자로 주어진 보조 페이지 테이블에 페이지 구조체를 삽입합니다. 이 함수에서 주어진 보충 테이블에서 가상 주소가 존재하지 않는지 검사해야 합니다.

Frame Management

프레임 구조체

include/vm/vm.h 에 물리 메모리를 뜻하는 struct frame 가 선언되어 있습니다.
프레임 관리 인터페이스를 구현하는 과정에서 다른 멤버들을 추가할 수 있습니다.

/* The representation of "frame" */
struct frame {
  void *kva; // 커널 가상 주소
  struct page *page; // 페이지 구조체를 담기 위한 멤버
};

구현할 함수들

static struct frame *vm_get_frame (void);

위의 함수는 palloc_get_page 함수를 호출함으로써 당신의 메모리 풀에서 새로운 물리메모리 페이지를 가져옵니다. 유저 메모리 풀에서 페이지를 성공적으로 가져오면, 프레임을 할당하고 프레임 구조체의 멤버들을 초기화한 후 해당 프레임을 반환합니다.
당신이 frame * vm_get_frame 함수를 구현한 후에는 모든 유저 공간 페이지들을 이 함수를 통해 할당해야 합니다.
지금으로서는 페이지 할당이 실패했을 경우의 swap out을 할 필요가 없습니다. 일단 지금은 PANIC ("todo")으로 해당 케이스들을 표시해 두십시오.

bool vm_do_claim_page (struct page *page);

위 함수는 인자로 주어진 page에 물리 메모리 프레임을 할당합니다. 당신은 먼저 vm_get_frame 함수를 호출함으로써 프레임 하나를 얻습니다(이 부분은 스켈레톤 코드에 구현되어 있습니다). 그 이후 당신은 MMU를 세팅해야 하는데, 이는 가상 주소와 물리 주소를 매핑한 정보를 페이지 테이블에 추가해야 한다는 것을 의미합니다.
위의 함수는 앞에서 말한 연산이 성공적으로 수행되었을 경우에 true를 반환하고 그렇지 않을 경우에 false를 반환합니다.

bool vm_claim_page (void *va);

위 함수는 인자로 주어진 va에 페이지를 할당하고, 해당 페이지에 프레임을 할당합니다. 당신은 우선 한 페이지를 얻어야 하고 그 이후에 해당 페이지를 인자로 갖는 vm_do_claim_page라는 함수를 호출해야 합니다.

0개의 댓글