Swapping: Mechanisms

박정빈·2024년 4월 7일

운영체제

목록 보기
16/25

지금까지는 주소 공간이 물리 메모리에 들어갈 정도로 작다고 가정했다. 하지만 이제는 대규모 주소 공간에 대해 생각해보겠다. 그러면 충분한 공간이 있는지 확인하지 않아도 된다. 대규모 주소 공간을 지원하기 위해 사용하지 않는 주소 공간의 일부를 하드 디스크 드라이브에 보관한다. 하드 디스크는 크지만 느리다. 이를 위해 스왑 공간(swap space)을 추가해서 가상 메모리라는 환상을 유지할 수 있다.

주소 공간을 지원하기 위한 장치가 하드디스크여야할 필요는 없다.
단지 크고 느린 장치가 있다고 생각하자

Swap Space

디스크에 페이지를 이동하기 위해 디스크에서 일정한 공간을 예약해야한다. OS에서는 이런 공간을 swap space라고 한다. 우리는 OS가 swap space에 대해 페이지 단위로 읽고 쓸 수 있다고 가정할 것이다. 이를 위해 OS는 특정 페이지의 디스크 주소를 기억해야한다. 스왑 공간의 크기는 중요하며, 시스템에서 사용중인 최대 메모리 페이지 수를 결정한다. 일단은 엄청 크다고 가정해보자.

아래 예제를 통해 살펴보자. 세 개의 프로세스(Proc 0, Proc 1, Proc 2)가 물리적 메모리를 공유하고 있다. 하지만 이들은 메모리에 일부 페이지만 가지고 있으며 나머지는 디스크의 swap space에 있다. Proc 3는 모든 페이지가 디스크에 있어서 실행되고 있지 않음을 알 수 있다.
Physical Memory and Swap Space

Present Bit

디스크로 페이지를 스왑하는데 필요한 장치가 있다. 이를테면 TLB가 있는 시스템이라고 생각해보자

메모리 참조가 발생하는 경우를 상기해보자. 하드웨어는 가상 주소를 물리적 주소로 변환한다. 가상주소에서 VPN을 추출하고 TLB hit를 확인하고 hit 이면, TLB에서 가져온다.
그러나 TLB miss 일 경우 하드웨어는 메모리에서 페이지 테이블을 찾고 PTE를 찾는다. PTE에서 PFN을 추출하여 TLB에 저장하여 TLB hit를 만든다.

페이지를 디스크로 스왑한다면 과정이 조금 달라진다. 하드웨어가 PTE를 살펴보았는데 물리 메모리에 없을 수 있다. 하드웨어가 이를 확인하는 방법은 Present Bit를 사용하는 것이다. 이 비트가 0이면 페이지가 디스크에 있다는 뜻이다. 물리 메모리에 없는 페이지에 접근하면 Page Fault가 발생한다. Page Fault가 발생하면, Page Fault Handler가 이를 처리해야한다.

Page Fault

하드웨어 관리형 TLB 시스템, 소프트웨어 관리형 TLB 시스템 모두 Page Fault가 발생하면, Page Fault Handler가 이를 처리해야한다.

OS는 처리를 위해 페이지를 메모리로 스왑해야한다. OS는 PTE에 PFN을 저장하면서 페이지 테이블에서 페이지를 찾는다. Page Fault를 받으면 OS는 페이지 주소를 찾기 위해 PTE를 확인하고 메모리로 가져오기 위해 디스코 요청을 보낸다.

디스크 I/O가 완료되면, OS는 페이지를 메모리에 존재하는 것으로 표시하고 PFN을 업데이트하고, 명령을 다시 실행한다. I/O가 진행되는 동안 프로세스는 Blocked 상태가 되서 다른 프로세스를 실행시킬 수 있다.

메모리가 다 차면?

만약 페이지를 스왑할 메모리가 가득 차 있다면 다른 페이지를 page out 할 수 있다. 이런 교환 정책을 페이지 교체 정책(page-replacement policy)이라고 한다. 효율적으로 동작하는 정책을 사용하지 않는다면, 느린 디스크의 사용으로 전체 프로세스가 느려질 수 있다.

Page Fault Control Flow

프로그램이 메모리에서 데이터를 가져올 때 어떻게 되는거지?
아래 코드는 변환시 하드웨어의 작업과 Page Fault시 OS의 작업이다.

  • Page-Fault Control Flow Algorithm (Hardware)
VPN = (VirtualAddress & VPN_MASK) >> SHIFT
(Success, TlbEntry) = TLB_Lookup(VPN)
if (Success == True) // TLB Hit
	if (CanAccess(TlbEntry.ProtectBits) == True)
		Offset = VirtualAddress & OFFSET_MASK
		PhysAddr = (TlbEntry.PFN << SHIFT) | Offset
		Register = AccessMemory(PhysAddr)
	else
		RaiseException(PROTECTION_FAULT)
else // TLB Miss
	PTEAddr = PTBR + (VPN * sizeof(PTE))
	PTE = AccessMemory(PTEAddr)
	if (PTE.Valid == False)
		RaiseException(SEGMENTATION_FAULT)
	else
		if (CanAccess(PTE.ProtectBits) == False)
			RaiseException(PROTECTION_FAULT)
		else if (PTE.Present == True)
         	 // assuming hardware-managed TLB
          	TLB_Insert(VPN, PTE.PFN, PTE.ProtectBits)
          	RetryInstruction()
        else if (PTE.Present == False)
          	RaiseException(PAGE_FAULT)
  • Page-Fault Control Flow Algorithm (Software)
PFN = FindFreePhysicalPage() //물리 메모리에서 free page 찾기 없으면 return -1
if (PFN == -1) //사용 가능 페이지가 없으면,
	PFN = EvictPage() // replacement algorithm 메모리에서 페이지 제거
DiskRead(PTE.DiskAddr, PFN) // sleep (wait for I/O) 디스크에서 페이지를 읽어와서 물리 메모리에 로드
PTE.present = True // update page table: 이제 페이지가 있다고 표시 1
PTE.PFN = PFN // (present/translation) 표시 2
RetryInstruction() // page fault 시점의 명령 계속

When Replacements Really Occur

사실 메모리가 가득 차있을때 페이지를 교체하는 것은 비 현실적이다.
작은 양의 메모리를 유지하기 위해 대부분의 OS는 high watermark(HW)와 low watermark(LW)를 가지고 있다. OS가 사용가능한 페이지가 LW 미만입을 감지하면, 메모리를 해제하는 백그라운드 스레드가 실행된다. 이 스레드는 HW 페이지가 있을때 까지 페이지를 해제한다. 백그라운드 스레드는 종종 swap daemon 또는 page daemon 라고 불린다.

여러 교체를 한 번에 수행하면 성능 최적화가 가능해진다. 여러 페이지를 클러스터링하거나 그룹화하여 스왑 파티션에 한 번에 기록한다. 이렇게 하면 디스크의 탐색 및 회전 오버헤드가 줄어들어 성능이 향상된다.

0개의 댓글