3 분 소요

pintos VM 진행 중 알게된 점들을 정리하기

일부 진행 중 궁금하였던 내용과 알게된 내용을 정리하는 용도의 TIL

커널 영역과 물리 메모리, 페이지 교체

운영체제가 실행되고 동작하는 ‘커널 영역’은
이에 필요한 ‘코드’와 ‘데이터’ 등이 상주하는 공간이다

이 영역은 ‘물리 메모리’(DRAM)에 상주하며
‘페이지 교체’의 대상이 되지 않는다

이는 여러가지의 이유를 포함하고 있는데

  • 커널은 언제든지 사용과 접근이 가능해야 함
    (시스템의 안정성과 보안을 담당하기에)
  • 하드웨어와 메모리를 제어해야 하기에,
    이들의 효과적인 처리를 위하여 ‘커널 공간’을
    Page Swap 하느라 ‘딜레이’ 되어서는 안됨
  • 커널 공간이 메모리에 상주하여 성능 저하를 막을 수 있음

추가적으로 ‘커널 공간’은 메인 메모리의 ‘고정된 주소’에 상주한다
이를 통해 ‘커널 공간’에 존재하는 Page Table에 안정적으로 접근이 가능하고
또한 이러한 Page Table 들이 올바른 매핑 주소를 유지할 수 있도록 한다
(pintos에서 pml4와 spt를 이용할 때, palloc 을 ‘유저 공간’에 선언하지 않는 이유)

  • TMI : 커널 공간이 고정된 주소 영역이면 ‘보안’에 취약하지 않나?
    이를 위하여 고안된 기법이 ASLR(주소 공간 무작위 배치)이다
    이 기법을 통해 ‘사용자 프로그램’이 실행될 때,
    ‘사용자 공간’을 무작위로 배치하여
    ‘커널 영역’을 예측할 수 없도록 한다

Segmentation 과 Paging 기법

Segmentation과 Paging을 동시에 이용하는
Segmantaion Paging 기법의 경우,
‘선형 공간’ 이라는 개념을 이용하여
추가적인 변환을 이용한다

따라서
VA(가상 주소) -> 선형 공간 주소 -> PA(물리 주소)
의 변환 방식을 가지게 되는데

VA -> 선형 공간 주소 인 경우, Segment Table을 이용하고
선형 공간 주소 -> PA 인 경우, Page Table을 이용한다
(참고로 이 과정은 전부 MMU에서 일어난다)

MMU는 Segment Table을 참고하여
‘해당 세그먼트’의 ‘base’와 ‘offset’을 통하여 ‘선형 주소’를 알아낸다
이후, 이러한 ‘선형 주소’를 통하여
Page Table을 참고하여 ‘물리 주소’를 반환

‘선형 공간’을 쓰는 이유는 무엇일까?
이러한 방식을 통해 ‘여러 이점’을 누릴 수 있는데

  • 각 세그먼트 (heap, stack 등)가 자신만의 ‘선형 주소 공간’을 가지기에
    메모리 할당이 간편하다
    (이를 위하여 각 세그먼트 공간이 각각의 page table을 가진다)
  • 모듈화로 인한 프로세스 간의 충돌 방지, 그로 인한 보안 강화
    (VA -> 선형 공간, 선형공간 -> PA 의 2가지 변환 과정에 따라
    더 많은 예외를 각각 segmantion fault와 page fault로 처리할 수 있음)
  • 가상 주소 공간이 세그먼트로 분리되기에, 효율적인 관리 가능
    (각각의 segment가 Access 및 control 비트를 가진다)

다만 몇가지 단점이 존재하기에 Paging 기법과 Segmentation 기법이 선호되기도 한다

  • 각각의 segment가 가지는 page table 로 인한 추가적인 메모리 할당
  • segment table과 page table을 모두 관리해야 하는 복잡성
  • 2가지 기법으로 2번 변환하기에 가지는 오버헤드

이로 인하여 시스템 엔지니어는 각 기법의 특징을 이해해야 한다고 한다

  • TMI : Segmentation Falut?
    일반적으로 null 참조 혹은 유효하지 않은 주소를 참조할 때 나타나는 오류이다
    (즉, 잘못된 메모리 영역에 접근하는 경우를 뜻함)
    그렇다고 이 에러가 뜬다고 반드시 Segmetation 기법을 사용한다는 뜻은 아니다
    위에서 참고하듯, Segment Table은 각 Segment(Heap, stack 등)를 관리하기에
    현재 주어진 ‘가상 주소’가 올바르지 않은 ‘Segment’를
    참조하려 하기에 벌어지는 일이라고 볼 수 있다

    그렇기에 NULL, 잘못된 메모리 영역 접근, 권한 없는 접근 등에선
    VA의 접근 자체가 잘못되었기에
    ‘Segment Fault’가 일어난다고 표현할 수 있을 것이다
    (다만 Paging 기법만 사용한다면 Page Fault로 처리되겠지만…)

    일반적으로 VA가 ‘잘못된 가상 주소’를 사용할때 발생한다고 통용된다

pml4와 spt의 관계에 대하여

이전의 내용에도 포함됬지만 구현을 하며 조금 더 느낀 점은
project3에서 ‘swap’을 위해서
spt가 반드시 필요하다는 점이다

pml4는 순수하게 va와 pa만을 연결해주며,
각 ‘가상 메모리’가 swap out 되는 것은 고려되지 않는다

pintOS에서 vm_claim_page 를 통하여 swap_in 을 호출하여
각 ‘page’ 구조체의 swap_in 을 통해
file-backed 와 anony 메모리 타입에 따른
처리를 해주게 되는데

이 때, 보조적인 page table 등을 이용하여
필요한 데이터를 spt로 관리할 수 있음
(spt를 공통된 data 타입으로 관리하되, 내부적으로 union을 사용하여
다형성을 표현하게 된다)
(조금 더 정확히는 ‘swap-table’을 따로 구현한 것이긴 하지만)

  • TMI
    pml4의 Dirty bit 와 Access bit는
    x86-64 하드웨어가 1로 체크해준다
    (다만 0으로 만들지는 않기에 이는 OS가 재설정 해야 한다)
    (by git book)

일부 테스트 케이스에 대하여(swap)

swap-file , swap-iter 에서 계속해서 false가 뜨던 중
발견한 내용이였는데
놀랍게도 ‘페이지를 교체할 때’ 계속해서 ‘같은 페이지’를 교체하고 있었다
너무 수상해서 swap-in, swap-out 부분을 계속 들여다 보고도 이상한지 몰라서
victim page에 break point를 걸어보고 깨달은 것은…

 while (tempElem != endElem)
	{
		victim = list_entry(tempElem,struct frame,frame_elem);
		if(pml4_is_accessed(curr->pml4,victim->page->va) == true)
		{
			pml4_set_accessed(curr->pml4,victim->page->va,false);
		}
		else
		{
			startElem = tempElem->next;
			if(startElem == endElem)
			{
				startElem = NULL;
			}
			return victim;
		}
	}

그렇다…
tempElem 이 next element 로 넘어가는 부분이 빠져있었다…

 while (tempElem != endElem)
	{
		victim = list_entry(tempElem,struct frame,frame_elem);
		if(pml4_is_accessed(curr->pml4,victim->page->va) == true)
		{
			pml4_set_accessed(curr->pml4,victim->page->va,false);
		}
		else
		{
			startElem = tempElem->next;
			if(startElem == endElem)
			{
				startElem = NULL;
			}
			return victim;
		}
		tempElem = tempElem->next;
	}

가장 아래에 해당 부분을 넣어주니 테스트 케이스를 정상적으로 통과하였다

일부 테스트 케이스에 대하여(merge)

테스트 케이스 중 ‘merge’와 관련된 부분이 지속적으로 fail 발생하였기에
‘create’에 대한 syscall 부분에서 lock을 걸어주었다
이후, proecess_exec의 load에 해당하는 부분에 추가적으로 lock을 걸어주어
각 exec가 segment를 할당할 때,
race condition이 발생하는 것을 막아 merge 관련 test Case를 통과할 수 있었다

댓글남기기