Project3 Virtual memory

do young Lee·2023년 5월 16일
0

swjungle

목록 보기
4/4

Project3의 주제는 virtual memory이고 해당 part에서 구현해야 하는 부분은 다음과 같으며 내용을 정리한다.

  • Memory Management
  • Anonymous Page
  • Stack Growth
  • Memory Mapped Files
  • Swap In/Out

Pintos의 page와 frame

pintos에서는 Vitual memory를 구현하기 위해서 page 구조체와 frame 구조체를 선언하고 활용한다. 따라서 구현에 들어가기전에 pintos에서 구현되어있는 각 구조체를 먼저 살펴보고 이해한 바를 정리한다.

page structure

우선 pintos 의 struct page 의 코드는 다음과 같다.

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

	/* struct for hash */
	struct hash_elem hash_elem;
	/* 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
	};
};

page 구조의 첫번쨰 필드인 page_operation 타입인 operations들이 어떤 의미인지 파악하기 위해서는 struct page_operationswap_in, swap_out, destroy 매크로들을 같이 확인해봐야 한다.

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

#define swap_in(page, v) (page)->operations->swap_in ((page), v)
#define swap_out(page) (page)->operations->swap_out (page)
#define destroy(page) \
	if ((page)->operations->destroy) (page)->operations->destroy (page)

page-operation 구조체는 swap_in, swap_out, destroy 와 같은 함수형 포인터 필드들을 갖고있다. 함수형 포인터에 대해서는 pintos gitbook 에 다음과 같이 간단하게 설명되어 있다.
A function pointer is a pointer, just like any other pointers you've learned sofar, that points to a function, or an executable code within the memory. Function pointers are useful because they provide a simple way to call a specific function to execute based on run-time values without any checking.
page_operation 구조체가 함수형 포인터를 갖고 있도록 하는 이유는 page 구조체의 union 필드와 연결 지어서 이해해야 한다.

union 구조체는 하나의 메모리 영역에 다른 타입의 데이터를 저장할 수 있는 자료형이다. 다른 타입의 데이터를 저장할 수 있지만 동시에 존재할 수 있는 데이터 타입은 하나이다. 이때 union 구조체가 차지하는 공간은 여러가지 데이터 타입 중 제일 큰 공간을 차지하는 타입의 공간이 된다. 따라서 page 구조체는 uninit_page, anon_page(anonymous page), file_page(file_backed page) 중 하나의 struct 타입만을 필드로 갖는다. 각 구조체, 즉 page 타입 마다 다른 swap_in, swap_out, destroy 방법이 필요하며, 이 각각의 다른 operation들은 pintos 코드 상에서는 각각의 소스코드 파일내에 다음과 같이 정의 되어 있다. 처음에는 uninit 타입의 페이지로 존재한다. 페이지 타입이 변경되는 순간은 page fault가 발생하여 실제 데이터가 로드되는 순간이며(lazy loading), 이때 각각 변경되어야 하는 페이지 타입에 맞는 초기화 함수가 실행되며 이때 패이지 타입이 변경 된다.

/* uninit.c */
static const struct page_operations uninit_ops = {
	.swap_in = uninit_initialize,
	.swap_out = NULL,
	.destroy = uninit_destroy,
	.type = VM_UNINIT,
};
/* anon.c */
static const struct page_operations anon_ops = {
	.swap_in = anon_swap_in,
	.swap_out = anon_swap_out,
	.destroy = anon_destroy,
	.type = VM_ANON,
};
/* file.c */
static const struct page_operations file_ops = {
	.swap_in = file_backed_swap_in,
	.swap_out = file_backed_swap_out,
	.destroy = file_backed_destroy,
	.type = VM_FILE,
};

Memory management

Implementations

0개의 댓글