6/19 PintOS Project3(3)

JK·2023년 6월 20일

PintOS Project3(3)

오늘부터는 Anonymous Page의 구현을 시작합니다

Pintos에서 "Anonymous Page"는 가상 메모리 시스템에서 사용되는 개념입니다. 가상 메모리는 프로세스가 물리적인 실제 메모리보다 큰 가상 주소 공간을 사용할 수 있도록 해줍니다. 이 가상 주소 공간은 물리적인 메모리와 매핑되어 있으며, 필요한 페이지만 실제 메모리에 로드됩니다.

"Anonymous Page"는 디스크에 저장된 파일과 연결되지 않은 메모리 페이지를 의미합니다. 즉, 이 페이지는 파일로부터 읽어들이지 않고, 초기화되지 않은 메모리로 남아 있습니다. 일반적으로 힙 영역과 스택 영역 등에서 사용됩니다.

익명 페이지는 주로 동적 메모리 할당과 관련하여 사용됩니다. 프로세스가 동적으로 메모리를 할당할 때, 익명 페이지가 사용되어 추가적인 메모리 공간이 할당되고 초기화되지 않은 상태로 사용됩니다. 이러한 익명 페이지는 필요에 따라 페이지 부재가 발생할 때 실제 메모리에 로드되어 초기화됩니다.

Pintos에서 Anonymous Page는 가상 메모리 관리와 관련된 기능을 구현하는 데 사용되는 중요한 개념입니다. 이를 통해 효율적인 메모리 사용과 동적 메모리 할당을 가능하게 합니다.

vm_alloc_page_with_initializer

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. */
	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. */
		struct page *p = (struct page *)malloc(sizeof(struct page));

		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;
		}

		uninit_new(p, upage, init, type, aux, page_initializer);
		p->writable = writable;

		/* TODO: Insert the page into the spt. */
		return spt_insert_page(spt, p);
	}
err:
	return false;
}

위의 코드는 vm_alloc_page_with_initializer 함수입니다.

1. 함수 시그니처:

bool vm_alloc_page_with_initializer(enum vm_type type, void upage, bool writable, vm_initializer init, void *aux): 주어진 가상 주소(upage)에 페이지를 할당하고 초기화하는 함수입니다. 페이지의 타입(type), 쓰기 가능 여부(writable), 초기화 함수(init), 보조 매개변수(aux)를 인자로 받습니다. 페이지를 할당하고 초기화한 후 보충 페이지 테이블에 페이지를 삽입하고 성공 여부를 반환합니다.

2. 함수 동작:

  1. 주어진 가상 주소(upage)가 보충 페이지 테이블에 이미 할당되어 있는지 확인합니다. spt_find_page 함수를 사용하여 보충 페이지 테이블에서 주어진 가상 주소에 해당하는 페이지를 검색합니다. 페이지를 찾을 수 없는 경우 아래의 코드 블록을 실행합니다.

  2. 새로운 페이지를 할당하고 초기화하기 위해 동적으로 struct page 객체를 할당합니다. malloc 함수를 사용하여 struct page의 크기만큼 메모리를 할당하여 p에 할당된 메모리 주소를 저장합니다.

3.페이지의 초기화 함수를 선택합니다. 페이지의 타입(type)에 따라 초기화 함수를 선택합니다. switch 문을 사용하여 VM_TYPE 매크로를 사용하여 타입에 맞는 초기화 함수를 선택합니다. 현재 구현된 초기화 함수는 anon_initializer와 file_backed_initializer입니다.

  1. uninit_new 함수를 호출하여 페이지를 초기화합니다. uninit_new 함수는 페이지의 주소(upage), 초기화 함수(init), 타입(type), 보조 매개변수(aux), 페이지의 초기화 함수(page_initializer)를 인자로 받아 페이지를 초기화합니다.

  2. 할당된 페이지의 쓰기 가능 여부(writable)를 설정합니다.

  3. 보충 페이지 테이블에 페이지를 삽입합니다. spt_insert_page 함수를 호출하여 페이지를 보충 페이지 테이블에 삽입합니다.

  4. 페이지 할당 및 초기화, 페이지 삽입이 성공적으로 이루어진 경우 true를 반환합니다.

  5. 에러 처리 레이블(err)로 이동하여 false를 반환합니다.

이 함수는 주어진 가상 주소에 페이지를 할당하고 초기화한 후 보충 페이지 테이블에 페이지를 삽입하는 역할을 합니다. 페이지 할당, 초기화, 삽입의 세 단계로 이루어져 있으며, 페이지의 타입에 따라 적절한 초기화 함수를 선택하여 페이지를 초기화합니다.

uninit_initialize

static bool
uninit_initialize (struct page *page, void *kva) {
	struct uninit_page *uninit = &page->uninit;

	/* Fetch first, page_initialize may overwrite the values */
	vm_initializer *init = uninit->init;
	void *aux = uninit->aux;

	/* TODO: You may need to fix this function. */
	return uninit->page_initializer (page, uninit->type, kva) &&
		(init ? init (page, aux) : true);
}

위의 코드는 uninit_initialize 함수입니다.

1. 함수 시그니처:

bool uninit_initialize(struct page page, void kva): 주어진 페이지(page)를 초기화하는 함수입니다. 페이지의 초기화에 필요한 정보를 사용하여 페이지를 초기화하고 초기화 함수를 호출합니다. 페이지 초기화의 성공 여부를 반환합니다.

2. 함수 동작:

  1. 주어진 페이지(page)의 uninit_page 구조체를 가져옵니다. struct uninit_page *uninit = &page->uninit;를 통해 uninit 포인터가 페이지의 uninit_page 구조체를 가리키도록 합니다.

  2. 초기화 과정에서 사용할 초기화 함수(init)와 보조 매개변수(aux)를 가져옵니다. uninit 구조체의 필드인 init와 aux를 가져옵니다.

  3. uninit->page_initializer 함수를 호출하여 페이지를 초기화합니다. uninit->page_initializer 함수는 페이지의 초기화 함수입니다. 페이지의 타입과 가상 주소(kva)를 인자로 받아 페이지를 초기화합니다.

  4. init 함수가 존재하는 경우, init 함수를 호출하여 페이지를 추가적으로 초기화합니다. init 함수는 페이지의 보조 초기화 함수입니다. 보조 매개변수인 aux를 사용하여 페이지를 초기화합니다. init 함수가 없는 경우 항상 true를 반환합니다.

  5. 페이지 초기화와 보조 초기화가 모두 성공한 경우 true를 반환합니다. 그렇지 않은 경우 false를 반환합니다.

이 함수는 주어진 페이지를 초기화하는 역할을 합니다. 페이지의 초기화에 필요한 정보를 사용하여 페이지를 초기화하고, 보조 초기화 함수를 호출하여 페이지를 추가적으로 초기화합니다. 초기화와 보조 초기화의 성공 여부에 따라 true 또는 false를 반환합니다.

vm_anon_init

void vm_anon_init(void)
{
	/* TODO: Set up the swap_disk. */
	swap_disk = disk_get(1, 1);
	list_init(&swap_table);
	lock_init(&swap_table_lock);

	disk_sector_t swap_size = disk_size(swap_disk) / 8;
	for (disk_sector_t i = 0; i < swap_size; i++)
	{
		struct slot *slot = (struct slot *)malloc(sizeof(struct slot));
		slot->page = NULL;
		slot->slot_no = i;
		lock_acquire(&swap_table_lock);
		list_push_back(&swap_table, &slot->swap_elem);
		lock_release(&swap_table_lock);
	}
}

위의 코드는 vm_anon_init 함수입니다.

1. 함수 시그니처:

void vm_anon_init(void)는 함수의 시그니처입니다. void는 반환 값이 없음을 나타내며, vm_anon_init은 매개변수를 받지 않는 함수입니다.

2. 함수 동작:

  1. swap_disk를 설정합니다. disk_get(1, 1) 함수를 사용하여 인덱스가 1인 디스크를 가져옵니다. 이를 swap_disk에 할당합니다.

  2. swap_table을 초기화합니다. list_init 함수를 사용하여 swap_table을 빈 리스트로 초기화합니다.

  3. swap_table_lock을 초기화합니다. lock_init 함수를 사용하여 swap_table_lock을 초기화합니다.

  4. swap_disk의 크기를 확인하여 swap_size 변수에 할당합니다. disk_size(swap_disk) 함수를 사용하여 swap_disk의 크기를 바이트 단위로 가져온 뒤 8로 나누어 섹터 단위로 변환합니다.

  5. 0부터 swap_size까지 반복하면서 스왑 슬롯(struct slot)을 생성합니다. 각 스왑 슬롯은 slot 포인터로 동적으로 할당됩니다.

  6. 스왑 슬롯의 필드를 초기화합니다. slot->page는 NULL로 설정되고, slot_no는 반복하는 인덱스(i)로 설정됩니다.

  7. swap_table_lock을 획득하여 스왑 테이블에 스왑 슬롯을 추가합니다. list_push_back 함수를 사용하여 swap_table 리스트의 끝에 swap_elem 필드를 가진 스왑 슬롯을 추가합니다.

  8. swap_table_lock을 해제합니다.

이 함수는 익명 페이지 관리를 위한 초기화 과정을 수행합니다. 스왑 디스크(swap_disk)를 설정하고, 스왑 테이블(swap_table)을 초기화합니다. 그런 다음 스왑 슬롯을 생성하여 스왑 테이블에 추가합니다. 스왑 슬롯은 각각 스왑 영역의 일부를 나타내며, 스왑 슬롯에는 페이지(page)와 스왑 슬롯 번호(slot_no) 정보가 저장됩니다.

anon_initializer

bool anon_initializer(struct page page, enum vm_type type, void kva)
{
/ Set up the handler /
page->operations = &anon_ops;

struct anon_page *anon_page = &page->anon;
anon_page->slot_no = -1;
return true;

}

위의 코드는 anon_initializer 함수입니다.

1. 함수 시그니처:

이 함수는 매개변수로 struct page 포인터인 page, enum vm_type인 type, 그리고 void 포인터인 kva를 받으며, bool 타입의 값을 반환합니다

2. 함수 동작:

  1. 페이지의 operations 필드를 익명 페이지 연산(anon_ops)을 가리키도록 설정합니다. 이를 통해 페이지에 대한 익명 페이지 연산을 수행할 수 있게 됩니다.

  2. 페이지의 익명 페이지(anon_page) 구조체를 가져옵니다.

  3. 익명 페이지의 slot_no를 -1로 설정합니다. slot_no는 해당 페이지가 스왑 슬롯에 있는지 여부를 나타내는 값으로, -1은 스왑 슬롯에 존재하지 않음을 의미합니다.

  4. true를 반환하여 초기화를 성공적으로 완료했음을 나타냅니다.

이 함수는 익명 페이지의 초기화를 수행합니다. 페이지의 operations 필드를 설정하여 익명 페이지 연산을 지정하고, 익명 페이지의 slot_no를 -1로 설정하여 해당 페이지가 스왑 슬롯에 존재하지 않음을 나타냅니다.

profile
^^

0개의 댓글