[TIL] 12/2 금

da__ell·2022년 12월 2일
0

TIL

목록 보기
3/5

12월 2일 금요일

1. Supplemental page table의 구현 방안

supplemental page table을 일단 해쉬테이블로 구하는 것이 적절할 것 같다.
supplemental page table은 무슨역할을 할까?

The supplemental page table supplements the page table with additional data about each page. It is needed because of the limitations imposed by the page table's format. Such a data structure is often called a "page table" also; we add the word "supplemental" to reduce confusion.
-Kaist CS 330 -

💡 보조 페이지 테이블은 각 페이지에 대한 추가 데이터를 이용해서 페이지 테이블을 보조합니다. 페이지 테이블의 포맷으로 인해 생기는 제한들 때문에 보조 페이지 테이블이 필요합니다. 이런 자료구조는 종종 “페이지 테이블”로도 불리는데, 저희는 혼란을 방지하기 위해서 “보조”라는 단어를 붙였습니다.

권영진 교수님의 강의에서는 각각의 페이지에 대해서 데이터가 존재하는 곳(physical frame인지 disk인지, swap partition인지), 이에 상응하는 커널 가상주소를 가리키는 포인터, 페이지가 active인지 inactive인지 등을 보조데이터라고 한다.

위와 같이 페이지의 보조데이터를 담고 있는 자료구조를 보조페이지테이블이라고 한다.

과제에서는 보조페이지테이블을 원하는 대로 구성할 수 있다고 한다.

첫 번째는 세그멘테이션 두 번째는 페이지 방식이다.

세그멘테이션과 페이징을 알기 전에 먼저 세가지 개념을 알고 가는 것이 좋다.
주소 바인딩 / 스와핑 / 메모리 할당과 단편화이다.

2. 주소 바인딩

먼저 논리주소와 물리 주소에 대해서 알아야한다.

논리주소란?

프로세스가 실행을 위해 메모리에 적재되면, 프로세스를 위한 독자적인 주소공간이 생성된다. 이를 논리 주소라고 한다.
논리 주소는 CPU에 의해 프로그램에 실행되고 있을 때 만들어진다. 물리적으로 존재하는 주소가 아니고 개념적으로 존재하는 주소로 가상주소라고도 불린다. 논리주소를 물리주소를 가르킨다.

물리주소란?

메모리 상의 물리적인 주소. 사용자는 직접 물리주소에 접근하는 방식이 아닌 대응되는 논리구조로 접근한다. 프로그램들은 가상주소를 통해 프로그램이 이 가상주소에서 실행된다고 가정하여 실행된다.
실제로 프로그램을 실행하기위해서는 물리주소가 필요한데, MMU가 가상주소를 물리주소와 연결시켜야 한다.
이를 주소 바인딩이라고 한다.

그러면 주소 바인딩을 언제 실행되나?

논리주소에 대응하는 물리 주소를 언제 결정하느냐에 따라 3가지로 나눌 수 있다. 컴파일타임 바인딩 / 로드 타임 바인딩 / 실행 시간 바인딩이 있다

일단 실제로 많이 활용되는 실행시간 바인딩에 대해서 알아보자

말 그대로 실행할 때 물리주소를 바꾸는 것이다.

CPU가 주소를 참조할 때마다 해당 논리주소의 데이터가 물리 메모리의 어느 위치에 있는지 매핑 테이블 (i.e. 페이지 테이블)을 통해 확인한다.

실행할 때 더하기 연산을 하는 것이 특징인데 더하기 하는 위치가 하드웨어이다. 그럼 이와 별도로 연산을 수행하는 하드웨어가 필요하게 되는데, 이 때 MMU가 그 역할을 한다.

MMU란 CPU코어 안에 탑재되어서 가상 주소를 실제 메모리 주소로 변환하는 장치라고 한다.

그래서 변환을 어떻게 해주는 걸까? 이 부분에 대해서는 한계 레지스터, 기준 레지스터에 대한 개념도 같이 있어야 된다.

간단하게 이해한 것은 한계 레지스터 에서는 논리주소의 쵀댓값을 가지고 있고 기준 레지스터는 프로세스의 물리메모리의 시작 주소를 갖고 있다라는 정도로 일단 받아들이고 넘어가려한다.

CPU가 논리적 주소 100에 있는 데이터를 요청한다면
MMU는 기준 레지스터에 있는 물리주소의 시작값(예를들어 8000이라면) 과 논리주소의 값을 더하여 실제 주소 8100에 있는 데이터에 접근하는 방식이다. 이때 한계 레지스터는 논리주소의 최댓값을 갖고 있어서 프로세스마다 할당 된 주소범위를 벗어나지 않도록 하게 한다.

3. 스와핑

프로세스가 실행되기 위해서는 메모리에 있어야 한다. 하지만 메모리가 가득 찰 경우 임시로 예비 저장장치(-카이스트 핀토스에서는 스와핑 파티션)로 내보내어졌다가 다시 메모리로 올려질 수 있다.
메모리가 가득 차면 추가적으로 실행되는 프로그램은 스왑 파티션에서 실행된다.

• 스와핑(Swapping) : 메모리에 적재한 하나의 프로세스와 보조기억장치(backup store)에 적재한 다른 프로세스의 메모리를 교체하는 방법

프로세스 단위의 스와핑은 페이징 기법으로 발전한다.

4. 메모리 할당과 단편화

메모리 할당을 프로세스를 메모리에 할당하는 것을 의미한다. 메모리를 어떻게 분할하여 프로세스를 할당시키느냐에 따라 방식이 나뉜다.

  1. 고정분할 : 메모리를 똑같이 고정된 크기로 분할한다. 각 분할마다 하나의 프로세스를 할당한다. - 내부 단편화 발생
  2. 가변분할 : 프로세스가 필요로하는 크기에 맞춰 적절한 공간을 할당한다. - 외부 단편화 발생

메모리를 고정분할하는게 페이징. 메모리를 페이지 단위로 나누어서 분할하여 할당하는 방식이다.
일단 이 정도만 이해하고 바로 세그멘테이션에 대해서 정리해 봤다.

5. 세그멘테이션은 메모리주소를 가변 분할하는 방식이다.

프로세스에서 요청하는 크기에 맞춰 물리주소를 할당하여주는 방식이다. 최대한 적절한 크기의 주소를 할당하여 주기에 내부단편화는 발생하지 않지만 외부 단편화의 문제가 발생한다.

세그멘테이션으로 테이블을 구성하면 어떠한 방식으로 가상주소에서 물리주소로 접근하게 될까?

맨처음에 논리 주소의 접근 형태는 s,d의 형태로 이루어진다.
논리주소 (2,300)을 한다면 MMU에서 2번 엔트리에 있는 4300 시작물리주소 + 300 논리주소를 연산하여 물리주소 4600번지와 연결한다.
세그먼트 테이블에는 세그먼트 번호에 따라 시작 물리주소와, 논리주소의 한계값이 저장되어 있다. 이 한계값을 벗어나는 논리주소의 접근이 이뤄진다면, 예를 들어 (1,500)의 논리주소 접근이 이뤄진다면 다른 프로세스의 주소를 침범하는 것을 방지하기 위해 인터럽트가 발생하여 프로세스가 강제로 종료될 것이다.

6. 페이징은 메모리 주소를 고정 분할하는 방식이다.

페이지라는 정헤진 크기를 기준으로 메모리를 분할하는 방식이다. 고정적인 크기의 주소를 할당하기 때문에 내부 단편화의 문제가 발생한다.

페이지 테이블을 구성하면 어떠한 방식으로 가상주소에서 물리주소로 접근하게 될까?

페이징은 이미 정해진 단위에 따라 페이지가 나눠져 있다. 페이지 테이블은 각 페이지의 물리 주소를 저장하고 있으며, 프로세스의 가상메모리에서 접근하는 방식은 페이지 번호(엔트리) p와 오프셋(d)를 통해 이뤄진다. 페이지 번호 p를 확인하고 페이지 테이블은 그에 대응하는 페이지의 물리주소를 알려준다. 이를 통해 물리주소 페이지에 접근하여 해당 페이지의 오프셋 d에 접근하면 원하는 물리주소가 된다.

7. 앞으로의 계획

#ifdef VM
	/* For project 3 and later. */
	if (vm_try_handle_fault(f, fault_addr, user, write, not_present))
		/*이제 page fault가 발생하면 파일 또는 스왑 슬롯에서 파일을 가져와야 한다.*/
		return;
#endif
  1. 기존의 Pintos는 page fault를 일종의 버그로써 인식했다면, 앞으로는 파일 또는 스왑 슬롯에서 파일을 가져와야 한다.
    이를 위해 vm_try_handle_fault이라는 함수를 구현하여야 한다.
/* Return true on success */
bool vm_try_handle_fault(struct intr_frame *f UNUSED, void *addr UNUSED,
						 bool user UNUSED, bool write UNUSED, bool not_present UNUSED)
{
	struct supplemental_page_table *spt UNUSED = &thread_current()->spt;
	struct page *page = NULL;
	/* TODO: Validate the fault */
	/* TODO: Your code goes here */
	/*
	1. 보조 페이지 테이블에서 폴트가 발생한 페이지를 찾는다.
	-> spt_find_page (구현해야지)
	2. 만일 메모리 참조가 유효하다면 보조 페이지 엔트리를 사용해서 페이지에 들어가는 데이터를 찾는다.
	3. 페이지를 저장하기 위해 프레임을 획득.
	4. 데이터를 파일 시스템이나 스왑에서 읽어오거나, 0으로 초기화하는 등의 방식으로 만들어서 프레임으로 가져온다.
	5. 가상주소에 대한 페이지 테이블 엔트리가 물리 페이지를 가리키도록 지정한다 -> vm_do_claim_page
	*/
	return vm_do_claim_page(page);
}
  1. 과제 설명서를 참고해서 구현을 위해 필요한 함수들을 찾아 보았다. 함수들을 찾아봤지만 그 함수들조차 이제 구현을 다 해야한다.
/* Representation of current process's memory space.
 * We don't want to force you to obey any specific design for this struct.
 * All designs up to you for this. */
struct supplemental_page_table
{
	/*
	보조테이블을 구현한다.
	1. 세그멘테이션 테이블 : 주소를 요청하는 크기만큼 할당한다.
	2. 페이징 테이블 : 페이지 단위로 주소를 할당한다.
	해시 페이지 테이블로 구현??
	*/
};
  1. 가장 중요한 것은 먼저 supplemental_page_table을 구현하는 것이 중요하다. 일단 해당 페이지가 어디에 위치해 있는지에 대한 정보라던가.. 등과 같은 해당 페이지에 대한 정보를 담아주어야하는데, 어떤 정보를 담아주어야 할지 조금 더 공부해봐야 할 것 같다. 난관이 예상된다.
profile
daelkdev@gmail.com

0개의 댓글