✨ Virtual Memory (가상 메모리)
가상 메모리에 대해 너무 이해가 잘 안됐을 때 들었던 예시 중 가장 인상 깊은 비유가 있다.물리 메모리는 현실 세계를, 가상 메모리는 환상 세계를 의미한다고 보면 된다.현실 세계에서는 강도,살인 등 지저분 한 것들이 많듯이 물리 메모리도 프레임 단위로 데이터들이 흩어저있다.반면 가상 메모리는 프로세스에게 환상을 준다. 지금 "프로세스" 너는 CPU와 메모리를 독점하고 있고 세그먼트 별로 데이터들도 잘 정렬되어 있다는 착각을 주는 것이다.
- 프로세스에 독립적이고 보호된 주소 공간 제공
- 효율적인 메모리 사용과 물리 메모리 확장
- 메모리 보호 / 효율성 (디스크 스왑) / 유연성 (프로세스는 실제 물리메모리 주소 알 필요 없음)
- 페이지 단위(4KB)로 나뉨
✨ PT (Page Table)
- VA를 PA로 변환하기 위한 매핑 정보 저장
- 각 프로세스마다 독립적으로 관리
- 주로 CPU 및 MMU가 사용
- 단일 레벨 페이지 페이블
- 다단계 페이지 테이블
- 단일 레벨 페이지 테이블의 크기 문제 해결 (계층 구조로 나눔)
- 다수의 인덱스와 오프셋으로 나눔
- 페이지 디렉토리를 통해 하위 페이지 테이블 위치 찾음
- 하위 페이지 테이블에서 PPN을 가져옴
- PFN + PFO로 물리 주소 계산
PTE (Page Table Entry)
- VPN을 PFN으로 매핑하는 정보 저장하는 데이터 구조
- OS는 가상 페이지를 통해서 메모리에 어디에 있고, 어떤 상태인지를 파악
- PTE필드
- Present (물리 메모리 존재 여부)
- Writeable (쓰기 가능한지 여부)
- User (사용자 모드에서 접근 가능 여부)
- Accessed (페이지 최근 접근 여부)
- Dirty (페이지 수정 여부)
- PFN (VPN과 매핑된 프레임 번호)
- Swap Slot (스왑 디스크에 있는 페이지 위치 저장)
- Reserved (항후 확장을 위해 예약된 비트)
- ex) 가상 주소 0xCAFEBABE ( 32비트 주소 4KB 페이지 )
- VPN : 0xCAFEB (상위 20비트)
- VPO : 0xABE (하위 12비트)
여기서 부터는 키워드 추가 내용
Frame (프레임)
페이지 테이블과 대립 되는게 프레임 테이블이다.
- 물리적 메모리 사용 상태 관리
- 물리 메모리를 시스템 전역적 관리
- 프레임 사용 상태 관리 (빈 프레임, 사용 중인 프레임)
- 페이지 교체시, 메타 데이터를 제공하여 어떤 프레임을 선택할지 제공
- 시스템에 하나만 존재
- 프레임 필수 필드
- 페이지 상태 (빈 페이지 / 사용 중 /공유 중)
- 소유 프로세스
- 매핑된 VA
- 페이지 교체와 관련된 작업을 수행하기 위해 매핑된 VA 필요
- 매핑된 VA가 기록되지 않는다면, 페이지 테이블을 역으로 찾아야함
- 프레임 공유 상태 관리
- 교체 알고리즘 메타 데이터
- OS 커널이 프레임 테이블 참조
- 커널 메모리 공간에 위치
가상 메모리에 필요한 테이블 비교
1. Page Table (페이지 테이블)
- 가상 메모리의 페이지
- (단순히) VA와 PA 매핑 관리
- 물리 메모리 외부에 있는 페이지 추적 불가능
- PT는 CPU와 MMU가 직접 참조하여 매우 빠르고 단순해야 함
- 하드웨어에 의존적
- 프로세스마다 하나씩 존재
2. Supplemental Page Table (보조 페이지 테이블)
Pintos 교육용 OS에 페이지 테이블을 보조하기 위해 사용하는 자료 구조
- 페이지 테이블은 단순히 매핑 정보만 저장하여 추가 세부 정보 필요
- 보조 페이지 테이블은 각 프로세스의 가상 메모리 공간 관리
- Page fault 처리할 때, 가상 메모리 관리에 필요한 메타데이터 저장
- 가상 페이지 타입(VM_UNINIT, ANON, FILE)
- 데이터 위치 (디스크, 파일)
- 읽기/쓰기 권한, 메모리 존재 여부
- 소프트웨어 중심으로 세부 관리 담당
SPT와 PT에 대해서 명확히 아는 것은 PintOS에서 정말 중요하다 !!
두 테이블의 정보 개수는 SPT ≥ PML4 가 된다.
PML4는 물리 메모리에 매핑된 페이지만 저장하고 SPT는 모든 관리 중인 가상 페이지의 정보를 유지한다.
아래는 SPT가 포함하는 VA 와 포함되지 않는 VA를 나타냈다.
SPT가 포함하는 VA
- ELF 실행 파일 로드 시 코드,데이터 영역의 메타데이터 (대부분의 경우)
- 스택 확장하는 경우
- mmap 호출 하는 경우
- 페이지 폴트 처리 하는 경우
SPT가 포함하지 않는 VA
- 사용하지 않는 가상 주소
- 커널 메모리 주소
- 자동으로 매핑된 주소
3. Frame Table (프레임 테이블)
- 물리 메모리의 프레임
- VA 정보 저장하지 않음
- 대신 물리 프레임 상태(사용 여부, 소유 프로세스 등) 관리
- 시스템에 하나만 존재
- OS가 시스템 전반의 물리 메모리 관리할 때 사용
- 주요 필드
- 프레임 주소
- 프로세스 ID (이 프레임을 사용하는 프로세스 정보)
- PTE 포인터
- 프레임 상태 프레임 사용 중인지, 비워 있는지, 스왑 영역에 있는지)
- LOCK 상태
아래 과정을 통해 전반적인 과정을 이해해보자.
1. 프로세스가 가상 주소(VA) 0x8048000 접근 시도
- CPU는 PT를 확인하여 PA와 매핑되어 있는지 확인
- 매핑이 존재 함
- PA로 변환 후 메모리에 접근
- 매핑이 존재하지않음
- Page Fault 발생
2. 페이지 폴트 처리 (보조 페이지 테이블 확인)
- OS가 보조 페이지 테이블 확인
- VA가 어떤 타입의 페이지인지 ?
- 디스크에 있는지 스왑 테이블에 있는지 ?
- 필요시 페이지 초기화 (Zero Page)
3. 프레임 테이블에서 프레임 확보
- 프레임 테이블에서 빈 프레임 탐색
- 메모리 부족할 경우 교체 알고리즘
- 희생 프레임 선택
- Dirty 상태이면 데이터를 디스크 또는 스왑에 저장
- Clean 상태이면 변경된 내용이 없으므로 프레임 해제
4. 디스크에서 데이터 로드 및 페이지 테이블 업데이트
- 보조 페이지 테이블 정보를 기반으로 업데이트
- 디스크에 데이터를 읽어 물리 프레임 로드
- 또는 새 페이지 초기화
- 또는 스왑된 데이터 복구
- VA와 맞는 PA의 매핑 생성 및 PT 업데이트
5. 프로세스 실행 재개
- CPU는 갱신된 PT를 통해 VA를 PA로 변환
프레임 탐색 위치
(페이지 폴트 발생 시) OS가 페이지 로드하기 위해 탐색 할 위치
- 물리적 메모리
- 스왑 디스크 영역
- 파일 시스템 (ELF 파일의 디스크 영역)
- .text / .data 세그먼트에서 디스크 데이터를 읽어 물리 메모리에 로드
- Zero Page
- 초기화되지 않은 데이터(BSS 세그먼트)나 스택처럼 새로운 메모리 공간 요구
Q. 그렇다면 디스크 블록 상태에 있는 데이터가 어떻게 VA 주소를 알 수 있을까 ?
- OS가 ELF 파일의 구조와 메타 데이터를 활용
- ELF 헤더와 프로그램 헤더에 VA와 디스크 블록 간의 매핑 정보가 포함
- p_offset과 p_vaddr (세그먼트의 시작) 정보를 활용하여 디스크에서 데이터 읽음
더 자세한 내용은 아래 포스팅을 참고하자 !
✨ Translation Lookaside Buffer (TLB)
- 가상 주소를 물리주소로 변환을 가속화하기 위해 사용되는 캐시
- CPU 내부에 위치
- 페이지 테이블 참조 없이 가상 주소 변환 정보 빠르게 가져 올 수 있음
- 최근 사용된 PTE를 캐싱하여 PT 접근 시간 제거
- 일반적으로 수십~수백개 항목 저장
- TLB 항목
- VPN / PFN / 메타데이터
✨ Page Fault (페이지 폴트)
- VA를 참조했지만, 해당 주소가 물리 메모리에 매핑되지 않은 경우
- 메모리 부족 문제를 해결하기 위한 매커니즘
- 발생 상황
- 가상 주소가 물리 메모리에 없는 경우
- 접근 권한 문제가 있는 경우
- 잘못된 주소를 참조한 경우
- 처리 과정
- CPU에서 PT에서 주소 변환 정보 없는 경우 페이지 폴트 발생시키고 OS에게 전달
- OS에서는 발생 상황 확인 후 PT 업데이트 및 프로세스 재개
- 페이지 폴트는 매우 비싼 작업 (처리 시간이 길음)
Page Fault가 일어나는 과정들이 궁금하면 아래 포스팅을 참고하면 된다.
✨ Lazy Loading
- 즉시 메모리에 로드하지 않고,필요할 때만 데이터를 메모리에 로드
- 초기 자원 사용을 최소화하고 성능 최적화
- VA가 실제로 참조될 때 페이지 폴트를 통해 로드
- 필요한 데이터만 디스크에서 읽어 불필요한 디스크 작업 줄임
- 페이지 폴트 오버헤드 발생
- 활용 사례
- 실제 데이터 참조 시점에 로드 (.text, .date 세그먼트)
- 파일 메모리 매핑 후, 실제 참조되는 페이지만 메모리 로드 (mmap)
- 스택 확장 (스택 영역에 접근할 때만 새 페이지 할당)
내가 착각했던 부분으로 프로그램이 실행 될 때 모든 VA가 PA와 즉시 매핑되지 않음 !!
(페이지 테이블은 프로그램 실행 초기에 완전히 완성된 상태가 아니고 점진적으로 만들어지고 갱신)
Demand Paging
- 실행 파일이 메모리에 매핑되었지만, 데이터가 로드되지 않음
- 데이터에 접근 → 페이지 폴트 발생
- 디스크에 읽어와 메모리에 로드
- 페이지 폴트 발생한 시점에 해당 페이지 메모리에 로드
- 가상 메모리 시스템 / 스왑 시스템에 주로 사용
Lazy Loading과 Demand Paging의 차이
- Lazy Loading
- 자원 및 데이터 관리
- 다양한 단위 (파일,이미지, 객체 등)
- File-baked Page 로드 시 사용
- 초기 로드 시간과 리소스 사용량 최적화
- Lazy Loading은 더 넓은 범위에서 사용되는 일반적인 기법
- Demand Paging
- 가상 메모리 시스템
- 페이지 단위로 메모리 효율적 관리
- 페이지 (4KB)
- 스왑 디스크에서 페이지 로드
- 운영체제의 가상 메모리 관리에 특화
✨ Page Replacement Policy (페이지 교체 정책)
- 메모리가 부족할 때 교체할 페이지 결정하는 알고리즘
- 목표 (페이지 폴트 횟수 최소화 / 디스크 오버헤드 감소 / 시스템 성능 최적화)
- FIFO (Frist-In-First-Out)
- 가장 먼저 메모리에 적재된 페이지 교체
- 구현이 간단 (큐 자료구조)
- 오래된 페이지가 자주 사용되는 경우도 제거
- LRU (Least Recently Used)
- 가장 오래 사용되지 않은 페이지 교체
- 각 페이지의 최근 사용 시간 추적해야해서 관리 복잡
- 구현을 위해 Accessed 비트 필요 (하드웨어 지원)
- Clock (Second-Chance Algorithm)
- LRU의 근사 알고리즘 (Accessed 비트 사용)
- 원형 큐로 페이지 관리
- 추가적인 하드웨어 지원 없이도 효율적으로 작동
- LFU (Least Frequently Used)
- 가장 적게 참조된 페이지를 교체
- 자주 사용되는 페이지를 메모리에 유지
- 페이지 참조 횟수를 추적해야해서 구현이 복잡
- Random Replacement
- 임의의 페이지를 선택하여 교체
- 구현이 매우 간단
✨ Swap Disk (스왑 디스크)
- 물리 메모리가 부족할 때 임시 데이터 저장하는 디스크
- 페이지 교체 정책을 통해 스왑 아웃 대상 페이지 선택 후 스왑 디스크에 저장
- 필요시 스왑 디스크에서 페이지 스왑 인
- 스왑 디스크는 디스크에 존재
- 디스크에 존재는 하지만 페이지 단위로 관리 (4KB)
- 일반 디스크는 파일 시스템을 통해 관리 하지만, 스왑 디스크는 페이지 테이블과 직접 연동
- 직접 연동하여 더 빠른 데이터 처리 가능
- OS는 스왑 디스크를 RAM 처럼 취급
- 스왑 디스크는 파일 시스템 구조가 없음
- 예를 들어 디렉토리 테이블, inode 와 같은 파일 시스템 구조
- 파일 시스템의 탐색 등의 오버헤드를 제거하고 페이지 번호 기반 직접 접근으로 성능 극대화
- 스왑 디스크의 (단순한 구조가 주는) 이점
- 스왑 테이블과 슬롯 번호를 통해 빠른 데이터 접근
- 효율적인 메모리 관리
참고로 프로세스가 처음 실행될 때는 일반적으로 스왑 디스크로 가지 않고, 코드와 데이터 세그먼트를 메모리에 로드한다.
일반 파일 시스템 (읽기)
- 디렉터리 구조 탐색
- 파일 메타데이터 접근 (inode)
- 데이터 블록 읽기
스왑 디스크 접근
- 페이지 테이블 확인
- 스왑 슬롯에서 해당 데이터 위치 확인
- 데이터 읽기
스왑 슬롯
- 스왑 디스크에서 페이지 단위로 데이터를 저장하는 공간
- 스왑 슬롯의 크기는 페이지 크기와 동일 (4KB)
참고로 프로세스의 스택과 힙 영역은 프로세스 종료 후 디스크에 저장되지 않는다.
보통 스택과 힙의 데이터는 일시적인 실행 데이터를 저장하기 때문이다.
만일 mmap (메모리 매핑된 파일) 로 데이터를 관리하는 경우, 해당 데이터는 디스크에 기록 될 수 있다.
하지만 실행 중 메모리가 부족해 스왑 영역으로 페이지가 옮겨졌다면 프로세스 종료 시 스왑에서 제거된다.
✨ Anonymous Page
- 특정 파일에 매핑되지 않은 메모리 페이지
- 특정 파일의 데이터 기반이 아닌, 주로 프로세스의 동작 중에 동적으로 생성 (malloc)
- 이러한 페이지는 주로 스왑 디스크를 통해 관리
- 익명 페이지는 파일 시스템과 연결되지 않아서 익명
- 동적 메모리 할당
- 익명 페이지로 스택 공간
- 초기화 되지 않은 전역 변수 (.bss)
- mmap
- 프로세스의 임시 데이터 저장
- 프로세스 간 공유 불가능
Zero Page
- 모든 값이 0으로 초기화 된 메모리
- BSS 섹션이나 동적 메모리 할당 시 기본 초기화
- 초기화된 후 재사용
- memset으로 초기화는 CPU 성능 저하
- 실제 페이지 쓰기 작업일 때에만 새로운 프레임 할당
+@ Anonymous file
- 특정 디스크 파일과 연결되지 않고 메모리 영역만 매핑
- 주로 RAM에 저장되며 메모리 부족시 스왑 디스크 저장 가능
- 초기 데이터는 0으로 설정
- 플래그를 통해 프로세스 간 공유 가능
- 실제 파일과 연결되지 않으므로 파일 디스크립터가 필요하지 않음
- 디스크 I/O가 없어 빠르게 데이터 읽고 쓰기 가능
- 프로세스가 종료되거나 매핑이 해제되면 Anonymous file 자동으로 제거
✨ File-backed Page
- 특정 디스크 파일과 연결된 메모리 페이지
- 파일과 직접 연결되어 변경 사항이 파일에 반영
- 동일한 실행 파일 또는 라이브러리 실행하는 여러 프로세스가 같은 페이지 공유 가능
- 메모리 부족 시 페이지 교체 정책에 따라 메모리에서 제거될 수 있음
- 디스크 성능이 낮으면 병목현상 발생 및 구현 및 관리가 복잡
✨ Direct Memory Access (DMA)
- CPU 개입 없이 메모리에 직접 데이터 전송
- CPU의 작업 부하를 줄이고 시스템 성능 크게 향상
- I/O 장치가 CPU 없이 메모리 컨트롤러와 직접 통신 지원
- DMA 컨트롤러는 CPU와 독립적으로 동작
- CPU는 DAM 컨트롤러에게 소스/목적지 주소, 전송 크기 등의 정보 제공
- CPU 부하 감소, 빠른 데이터 전송, 효율적 대용량 전송 가능
- 복잡한 하드웨어 관리, 메모리 충돌, 낮은 실시간성
- CPU와 DMA가 동시에 메모리 접근할 경우 충돌 발생
- DMA 전송 완료될 때까지 장치 대기 할 수 있음
- OS가 I/O 장치를 메모리 주소 공간에 매핑하여 DMA가 I/O 장치와 메모리 간 데이터 전송
- DMA가 물리 주소를 사용해 메모리 접근
- ex) 디스크, 네트워크 카드, 그래픽 카드
'크래프톤 정글' 카테고리의 다른 글
Pintos Project3 - VM 시스템 초기화 (2) | 2024.12.05 |
---|---|
Pintos Project3 - Virture Memory Test case 트러블 슈팅 (read-boundary) (0) | 2024.12.05 |
Pintos Project3 - Page Fault Handler (Page Fault 전반적인 과정 이해하기) (0) | 2024.12.02 |
Pintos Project3 - VA와 디스크 데이터 매핑 과정 이해하기 (0) | 2024.12.01 |
Pintos Project2 - User Program 흐름 잡기 (0) | 2024.12.01 |