본문 바로가기
2️⃣ 개발 지식 B+/OS

[OS] QnA로 알아보는 Virtual Memory

by ddubbu 2024. 10. 9.

목표 : QnA를 통한 개념 부족한 곳 채우기 (질문 리스트는 OSTEP 발췌 및 개인적인 궁금증)

 

틀린 부분 피드백은 언제든 환영 🙌


 

Q. 해당 노트북 사양을 분석하시오.
- 프로세스당 가상 주소 공간 최대 크기
- 물리 주소 크기

(유사 질문)
Q. 가상주소를 맵핑하는 물리주소는 어떤 HW를 지칭하는 걸까? RAM? Disk?

 

더보기

1-bit 는 0 / 1, 총 2개의 주소를 표현할 수 있다. n-bit 프로세서는 최대 (2^n) 개의 논리 주소 공간을 가질 수 있다. 즉, 64bit는 18.4EB (K < M < G < T < P < E)

 

시스템이 물리적으로 사용할 수 있는 메모리 공간은 RAM의 크기로, 8GB

하지만, OS의 메모리 사용 및 시스템 예약 메모리 등으로 가용 물리 주소 공간은 7.8G으로 감소했다.

 

Q. 이론적으로는 가상 주소 공간은 매우 큰데, 결국은 RAM 크기 만큼만 제한될 것 같아. (혹여 Swap In/Out을 한다해도 RAM + HDD 크기만큼만 일 것 같고)
왜 Virtual Memory 기술이 등장한걸까?

(유사 질문)
Q. 32Bit는 4G 가상 주소 공간을 가지잖아 그럼 RAM 8G 짜리를 지원하기 위해 33Bit 로 확장하면 되지 않을까? 왜 과하게 64bit로 늘린거야
더보기

우선 CPU를 추상화한게 Process, Thread 인것처럼, 메인 메모리의 추상화를 VM이 제공한다. 각 프로세스에 하나의 크고 통합된 사적 주소공간과 함께 프로세스 간 독립성, 확장성, 효율적인 관리 등의 기능을 제공한다. 하지만, 가상 주소 공간의 크기가 크더라도, 물리 메모리(RAM)의 한계와 디스크 스왑 공간의 한계 때문에 실제로 감당할 수 있는 프로세스의 수에는 제한이 있다.

 

그리고 현대 컴퓨터는 64GB 혹은 그 이상의 RAM을 지원해야하고, 더 큰 정수 및 부동 소수점 연산을 빠르게 처리할 필요성이 생겼다. 현재와 미래의 다양한 요구 사황을 지원하기위해 설계되었다.

 

Q. 물리 주소 단위는 왜 Byte 인거야?
int 자료형만 봐도 4byte인데, 그럼 주소 4칸을 차지하는거야?

(유사 질문)
Q. 그럼 가끔 주소를 hex로 표현하는건 뭐야?
더보기

Byte : 현대 컴퓨터의 기본 단위로서 주소 지정의 단순화를 위함.

데이터 타입에 따라 필요한 바이트 수만큼의 연속된 주소를 차지한다.

그리고 16진수는 사람이 읽고 이해하기 쉽게 주소를 표현하는 데 도움된다.

 

Q. 프로세스마다 Logical Address 주소 공간이 만들어진다면, Context Switching 할 때 어떻게 보관하지? 레지스터와 달리 보관할 정보가 많을 것 같아서
더보기

각 프로세스의 PCB (Process Control Block)에는 해당 프로세스의 페이지 테이블 정보가 저장되어있음

새 프로세스로 전환 시, 복원된 페이지 테이블을 활성화함. 그리고  MMU는 페이지 테이블 기준을 업데이트 받음

 

페이지 테이블 데이터 또한 RAM에 저장 (부족 시 디스크로 일부 스왑될 수 있음)

 

[만약에] 프로세스가 전체 가상 주소 공간을 차지할 시 페이지 테이블이 차지하는 총 메모리 공간은?

64bit 프로세스 (48bit만 가용한다고 가정), 페이지 크기 4KB, PTE 크기 8byte

4-Level Page Table : 각 테이블은 (2^9)512개의 엔트리를 가진다고 가정 = 512 PTE * 8byte = 4KB

 

따라서 4KB x (1+512+512^2+512^3) = 512G

하지만, 실제로는 대부분의 프로세스가 전체 주소 공간을 사용하지 않기 때문에 실제 차지하는 공간은 훨씬 적다.

 

Q. 왜 Page Size는 4KB가 표준이 되었을까?
더보기

x86 표준화

페이지 테이블의 크기를 간단히 줄일 수 있는 방법은 페이지 크기를 늘리는 것이다. 하지만, 내부 단편화 및 메모리가 금방 고갈되는 현상이 발생해서 적절한 사이즈 설정이 필요

 

Q. N-Level Paging 덕분에 더 큰 (예로 32TB) 가상 주소 공간을 표현할 수 있다고 하는데 단계별로 살펴보고 싶다.

(유사 질문)
Q. 하지만, 일반적으로 64bit 프로세스의 주소 공간이 32TB로 언급되는 이유는? 
더보기

* 일반적으로 현대 OS에서는 각 단계에서 페이지 테이블 엔트리 수를 512로 설정하고 있음 (2^9 = 512)

 

64bit 프로세스이지만, 4단계 페이지 테이블 구성 위해 16bit는 미사용

(페이지 테이블 인덱싱 비트 = 4*9 = 36bit 페이지 오프셋 = 12bit)

 

[1단계] PML4 (Page Map Level 4) 512개의 엔트리, 각  512GB 주소 공간을 관리

[2단계] PDPT (Page Directory Pointer Table) 512개, 각 1GB

[3단계] PD (Page Directory) 512개, 각 2MB

[4단계] PT (Page Table) 512개, 각 4KB

 

총 주소 공간 = 512(PML4 엔트리)×512(PDPT 엔트리)×512(PD 엔트리)×512(PT 엔트리)×4(KB) = 256TB

 

**

 

64비트 프로세스가 이론적으로는 16EB의 가상 주소 공간을 지원할 수 있지만, 실제로는 다양한 이유로 32TB로 제한되는 경우가 많다.

 

Q. Convert VA to PA 상황에서, 단계별로 이슈 및 해결 방안 정리
(Hint) 전체 로드 > Segmentation > Paging > TLB + Page Fault > Multi-Level Paging > Swap In/Out > Page In/Out

 

 

Q. 잠만, 잘못된 주소 참조할 때 Sementation Fault 뜨잖아. Page Fault 가 아니라. 그럼 현재 기법은 Segmentation 기법인거인가?

(유사 질문)
Q. Page Fault를 개발하면서 본적이 없는데 언제 발생하는거

 

더보기

현대 운영 체제는 보통 세그멘테이션과 페이지 기법을 조합하여 사용한다.

- 프로세스는 가상 주소 공간을 세그먼트로 나누고,

- 각 세그먼트는 페이지 단위로 관리됩니다.

 

이러한 조합으로 인해 두 가지 오류가 모두 발생할 수 있다.

  • Segmentation Fault : 주로 프로그램 단에서 발생. 주로 잘못된 포인터 참조, 배열의 경계를 초과하는 접근, NULL 포인터 역참조 등이 원인
  • Paging Fault : 운영 체제 내부에서 발생. 페이지가 메모리에 없거나, Lazy Loading, 페이지 교체 등이 원인

 

 

(핀토스 Project3 키워드) Anonymous Page, Memory Mapped Files
  • Anonymous Memory : 특정 파일에 연결되지 않은 메모리 여역, 프로세스가 메모리를 요청 시 동적으로 할당 (malloc)
  • Backed Memory : 특정 파일이나 디바이스와 연결된 메모리, 프로세스가 종료되어도 해당 메모리에 저장된 데이터는 파일로 남아있음 (mmap)
    • Memory Mapped Files: 파일 시스템의 파일을 프로세스의 가상 주소 공간에 직접 매핑하여 직접 접근할 수 있게하는 기술

 

mmap 다양한 사용법
// [1] 파일을 메모리에 맵핑하고 그 내용을 읽는 방법
char *mapped = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);

// [2] 파일을 메모리에 맵핑하고 파일 쓰기
// MAP_SHARED 플래그를 사용하여 파일에 대한 변경 사항이 실제 파일에 반영
char *mapped = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

// [3] 메모리 할당
// 메모리를 파일에 매핑하지 않고, 
// 익명 메모리(Anonymous Memory)를 요청하여 메모리 블록을 할당할 수 있습니다.
char *mapped = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

 

 


 

아래는 추후 답변 예정

 

Q. (16.3 주소 공간) 메모리를 어떻게 가상화 하는가. OS는 물리 메모리를 공유하는 다수의 프로세스에게 어떻게 프로세스 전용의 커다란 주소 공간이라는 개념을 제공할 수 있는가?

 

Q. (18 주소 변환의 원리) 어떻게 효율적이고 유연하게 메모리를 가상화하는가
어떻게 효율적인 메모리 가상화를 구축할 수 있을까? 프로그램이 필요로 하는 유연성을 어떻게 제공하는가? 프로그램이 접근할 수 있는 메모리의 위치에 대한 제어는 어떻게 유지하는가? 메모리 접근을 어떻게 적절히 제한할 수 있는가? 어떻게 이 모든 것을 효율적으로 할 수 있는가?

 

 

Q. (19 Segmentation) 대용량 주소 공간을 어떻게 지원하는가
스택과 힙 사이에 잠재적으로 큰 빈 영역이 존재하는 주소 공간을 어떻게 지원할까? 크기가 4GB인 32비트 주소 공간을 상상해보자. 통상 프로그램은 단지 수 MB만 사용함에도 불구하고 주소 공간 전체가 메모리에 탑재되어야한다.

 

Q. (20 빈공간 관리) 빈공간을 어떻게 관리하는가
가변 크기의 요구를 충족시켜야 할 때, 빈 공간은 어떻게 관리되어야 할까? 단편화를 최소화하기 위해 어떤 전략을 사용할 수 있을까? 여러 대안들의 시간/공간 복잡도는 어떻게 되는가?

 

Q. (21 페이징: 개요) 페이지를 사용하여 어떻게 메모리를 가상화할 수 있을까
세그멘테이션의 문제점을 해결하기 위해 페이지를 사용하여 어떻게 메모리를 가상화할 수 있는가? 기본적인 기법은 무엇인가? 시/공간 오버헤드를 최소로 하면서 그 기법을 잘 작동하게 만들기 위한 방법은 무엇인가?

 

Q. (21.1) 페이징 관련 기본 질문
페이지 테이블은 어디에 저장되는가? 페이지 테이블의 내용은 무엇인가? 테이블의 크기는 얼마인가? 페이징은 시스템을 너무 느리게 만들지 않는가? 

 

Q. (22) 주소 변환 속도를 어떻게 향상할까?
주소 변환을 어떻게 빨리할 수 있을까? 페이징에서 발생하는 추가 메모리 참조를 어떻게 피할 수 있을까? 어떤 하드웨어가 추가로 필요하지? 운영체제가 어떤 식으로 개입해야할까?

 

Q. (22.5) 문맥 교환 시 TLB 내용을 어떻게 관리하는가?
문맥 교환 시 실행될 프로세스에게는 이전 프로세스가 사용한 TLB 정보는 의미가 없다. HW 또는 OS는 이러한 문제를 해결하기 위해 무엇을 해야할까?

 

Q. (23 페이징: 더 작은 테이블) 페이지 테이블을 어떻게 더 작게 만들까?
단순한 배열 기반의 페이지 테이블은 (흔히 선형 페이지 테이블이라고 불림) 크기가 크며 일반적인 시스템에서 메모리를 과도하게 차지한다. 어떻게 페이지 테이블의 크기를 줄일 수 있을까? 주요 개념들로는 무엇이 있는가? 새로운 자료 구조들은 어떤 비효율성을 갖는가?

 

Q. (24 물리 메모리 크기의 극복 : 메커니즘) 물리 메모리 이상으로 나아가기 위해서 어떻게 할까?
운영체제는 어떻게 크고 느린 장치를 사용하면서 마치 커다란 가상 주소 공간이 있는 것처럼 할 수 있을까?