csapp
버츄얼 메모리다
가상 메모리는 메인 메모리의 추상화다
메모리를 디스크에 있는 거대한 캐시로 보고 활성화 부분만 RAM에 둔다
효율(캐싱), 단순화(균일한 주소공간), 보호(프로세스 간 격리) 를 해준다
아주 좋으나 잘 이해해서 다뤄야 한다고 한다 ㅇㅇ
CPU에서 곧바로 PA(Physical Address)로 접근하는 식의 접근 법을 물리 주소 방식이라고 부른다
옛날에 자주 썼고 몇몇은 아직도 이러하지만
요즘은 대부분 가상 주소 방식을 사용한다
가상 주소 방식은 VA(Virtual Address)를 생성하고
메모리 관리 유닛 (MMU)이 이를 변환해 PA로 메모리에 접근한다
주소공간은 비음수 정수 주소의 정렬된 집합이다
가상 주소 공간 : 크기 N2ⁿ -> n비트 주소 공간 (보통 32비트 또는 64비트)
물리 주소 공간 : 크기 M(≈2ᵐ 가정) 로 실제 RAM 용량에 해당
데이터(바이트) 와 주소(속성) 를 분리함으로써 동일 바이트가 다른 주소(VA, PA)를 갖게 함
-> VM(가상메모리)의 기반
가상 메모리는 연속적 바이트 셀로 이루어진 배열이라 개념적으로 볼 수 있다
그리고 각 바이트는 고유한 가상주소 VA를 가지고 말이다
이 배열 내용은 메인 메모리에 캐시되어 가상 페이지 VP로 분할된다
각 VP의 크기는 $P = 2^p$ 바이트고 물리 메모리도 같은 크기의 물리 페이지 PP로 나뉜다
아무튼,
가상 페이지 집합은 세 부분으로 분할된다
Unallocated(미할당): 아직 VM이 할당(생성)하지 않은 페이지. 데이터가 없으므로 디스크 공간도 차지하지 않는다
Cached(캐시됨): 현재 물리 메모리에 캐시된 할당된 페이지
Uncached(비캐시): 할당되었지만 현재 물리 메모리에 캐시되지 않은 페이지
SRAM 캐시: CPU와 메인 메모리 사이의 L1/L2/L3 캐시
DRAM 캐시: VM 시스템이 가상 페이지를 메인 메모리(DRAM)에 캐시하는 계층
DRAM은 SRAM보다 ≥10배 느리고, 디스크는 DRAM보다 ≈10만 배 느리다
SRAM의 캐시 미스는 DRAM에서 처리된다
그리고 DRAM의 캐시 미스는 디스크에서 처리된다
즉, DRAM에서의 캐시 미스는 무척이나 뼈아프다!
그 결과 :
페이지 크기는 커진다
연관도가 높아진다
복잡한 교체 알고리즘을 사용한다
디스크 접근 시간이 커서 항상 wirte-back1을 쓴다
VM 시스템은 가상페이지가 DRAM 어딘가에 캐시 되었는지 결정 해야한다
이를 위해 특정 가상 페이지가 DRAM에 캐시되어있는지 판단
존재한다면 어느 물리 페이지에 있는지 탐색
미스라면 디스크에서의 위치를 알아내고 희생 페이지를 고른 뒤, 디스크 -> DRAM으로 가상 페이지 적재하여 교체한다
이 능력은 OS 소프트웨어, MMU의 주소 변환 하드웨어, 그리고 물리 메모리에 있는 데이터 구조인 페이지 테이블(page table) 의 결합이다
페이지 테이블은 페이지 테이블 엔트리(PTE)의 배열이다
VA 공간의 각 페이지에는 테이블의 고정 오프셋에 PTE가 있다
PTE에 유효필드가 DRAM에 캐시되었는지와 그 VP가 캐시된 물리 페이지 주소가 있다 볼 수 있다
DRAM 캐시는 완정 결합성이므로 물리페이지가 모든 가상페이지를 포함할 수 있다
CPU가 DRAM에 캐시된 가상메모리의 워드를 읽는다 치면 하드웨어는 이과 관련된 페이지 테이블 엔트리를 찾고 메모리에서 읽는다
그리고 이 주소의 유효 비트가 1이면 캐시되어 있다는 걸 알 수 있다
그리고 페이지 테이블 엔트리의 물리 메모리 주소를 이용해 해당 워드의 실제 주소 (물리주소 PA)를 구성한다
DRAM 캐시 미스 = 페이지 오류 $page fault$
커널이 개입해 디스크에서 해당 페이지를 가져와 처리한 뒤 명령을 재시작 한다
MMU가 PTE를 읽어 valid = 0 확인 -> 페이지 폴트 예외 발생
커널 페이지 폴트 핸들러 실행 -> 희생 페이지 선택
희생 페이지가 수정됨이면 디스크로 wrte-back1
요청 페이지를 디스크 -> DRAM으로 복사, PTE 갱신
오류를 낸 명령 재시작
VM에 새 페이지를 할당할 때에 커널이 디스크 상 위치를 확보하고 해당 VP의 PTE를 디스크 주소로 업뎃한다
미스 페널티가 큼에도 VM은 잘 작동한다 그 이유는 지역성 때문이다
프로그램은 매 시점에 작업 집합이라는 작은 페이지 집합만 집중적으로 사용한다
결과
작업 집합이 메모리에 올라온 뒤에는 대부분 히트 → 추가 디스크 I/O 없음
단, 작업 집합 크기 > 물리 메모리면 스래싱(thrashing): 페이지 인/아웃이 지속적으로 반복되어 성능이 급락. 프로그램이 비정상적으로 느리면 스래싱을 의심
가상 메모리가 실제 메모리보다 작을 때에도 가상 메모리는 사용되었다
메모리 관리에서도 용이 했으니 말이다
프로세스마다 독립 가상 주소 공간 & 페이지 테이블 보유. 이를 수요 페이징2과 결합해 메모리 사용/관리를 단순화 하였다
그 외 단순화:
링킹 단순화:
로딩 단순화:
공유 단순화:
할당 단순화:
malloc
등으로 연속 가상 페이지 k개를 요구하면, OS는 물리적으로 흩어진 k개 페이지에 매핑만 하면 됨(연속 물리 메모리 불필요).페이지 단위 접근을 제어
PTE에 권한 비트 추가해 제어
sup
: 커널 모드 전용 여부
(사용자 모드는 SUP=0
페이지만 접근)
READ
, WRITE
: 읽기/쓰기 허용
읽기 전용 코드 보호, 커널/타 프로세스 메모리 접근 차단, 공유 페이지도 권한에 따라 제한 가능
권한 위반 시 CPU가 일반 보호 예외 발생
-> SIGSEGV (segementation fault)