메모리 계층
메모리 계층은 레지스터, 캐시 메모리, RAM, 저장장치로 구성
이름 | 설명 | 휘발 여부 |
레지스터 | CPU 내의 작은 메모리 | O |
캐시 | L1,L2 캐시 지칭, L3 캐시도 있음 | O |
주기억장치 | RAM 의미 | O |
저장장치 | HDD/SSD | X |
이러한 계층이 있는 이유는 `경제성`과 `캐시` 때문임.
경제성: 16GM 램 VS 1TB HDD = HDD가 더 쌈 (속도 ∝ 돈)
대략 적인 속도 차이 ❓
L1 캐시: 약 1ns 이하 (나노초)
L2 캐시: 약 3~10ns
L3 캐시: 약 10~30ns
RAM (DDR4/DDR5): 약 50~100ns
SSD (NVMe 기준): 약 100,000ns (100µs)
HDD: 약 5,000,000ns (5ms)
ex) L3 캐시가 RAM 보다 10배~30배 빠름
캐시 (Cache)
데이터를 미리 복사해 놓는 임시 저장소
빠른 장치와 느린 장치의 속도 차이에 따른 병목 현상을 줄이기 위한 메모리
속도 차이를 줄이기 위해 계층과 계층 사이에 있느 계층을 `캐싱 계층` 이라고 함
예시) 캐시 메모리와 보조 기억 장치 사이 RAM = 보조기억장치의 캐싱 계층
캐시와 캐시 메모리 차이
`캐시`는 넓은 의미에서 다양한 영역에 존재할 수 있는 저장소.
`캐시 메모리`는 그 중 CPU 내부에 위치한 특화 개념 (= 캐시메모리 ∈ 캐시)
캐시 | 캐시 메모리 | |
정의 | 데이터에 빠르게 접근할 수 있도록 저장하는 공간 & 기술 | CPU, 메모리 간 속도 차이를 해결하는 고속 메모리 |
위치 | 여러 장치나 시스템에 존재 | CPU내부 또는 CPU 근처에 존재 |
기능 | 자주 사용되는 data 빠르게 저장 & 접근하도록 도움 | CPU 성능을 향상하기 위해 자주 사용되는 데이터 저장 |
예시 | CPU 캐시, 디스크 캐시, 웹 캐시 등 | L1, L2, L3 캐시 (CPU 캐시) |
L1, L2, L3 ❓ (L = Level)
성능과 비용을 고려해 계층적으로 나뉨
`L1 캐시`: 가장 빠른 응답 속도 제공 / CPU 코어 내부 존재
`L2 캐시`: L1 캐시자 작기 때문에 더 많은 데이터를 저장하면서도 빠른 접근을 위함
`L3 캐시`: 여러 코어가 데이터를 공유하면서, 캐시 미스 줄이기 위함
멀티 코어 CPU에서는 L1, L2는 코어별 존재, L3 캐시는 공유 데이터 저장
메모리 관리 기법
운영체제의 대표적인 역할 중 하나는 `메모리 관리`
컴퓨터 내의 한정된 메모리를 극한으로 사용해야 하므로
가상 메모리 (Virtual Memory)
메모리 관리 기법의 하나로 `주기억장치`의 부족한 물리적 공간을 `보조기억장치`의 일부 공간을 이용해 가상으로 늘려줌
∴ 사용자에게 매우 큰 메모리처럼 보이게 함
- 프로세스 전체가 메모리 내에 올라오지 않아도 실행 가능하도록 하는 기법
- 실행에 필요한 부분만 메모리에 올려 실행 (Demande paging)
- CPU는 MMU, TLB를 사용해 가상메모리 주소에 접근
- `Paging기법` 또는 `Segmentation 기법` 사용
- 가상 주소 (논리 주소): 가상적으로 주어진 주소, CPU & 프로세스 관점
- 물리 주소 (실제 주소): 실제 메모리 상에 있는 주소, 메모리 관점
📌 가상주소는 메모리 관리 장치(MMU)에 의해 실제 주소로 변환되므로,
사용자는 실제 주소를 의식하지 않아도 됨
페이지 테이블을 이용해 가상 주소를 물리 주소로 변환함
가상 메모리가 없다면 ?
초기 컴퓨터 시스템은 모든 프로그램이 물리적 메모리에 직접적으로 배치되어 실행
- 큰 규모의 프로그램 실행이 어려움
- 여러 프로그램 동시 실행 시 메모리 충돌 문제 발생 가능
ex) 연속 메모리 할당 방식
파일의 저장 위치를 메모리 상의 연속적인 위치에 저장. 👉 현재는 잘 사용하지 않음
`외부 단편화`: 메모리를 나눈 크기보다 프로그램이 커서 들어가지 못하는 공간이 발생하는 현상
이러면, 메모리가 있어도 쓰지 못하니 메모리 낭비로 이어짐.
그리고 물리 메모리보다 큰 프로세스 실행이 불가능한 문제점 존재
프로그램을 실행하려면 메모리에 올려야 함.
그런데, 프로그램이 차지하는 용량이 물리 메모리 용량보다 크다면 그 프로그램은 사용X
이러한 문제점을 해결하기 위해 가상 메모리를 사용함 (기법: 페이징, 세그멘테이션)
가상 메모리 프로그램 적재 방식
1) 디맨드 페이징 (Demand Paging)
가장 널리 사용되는 가상 메모리 적재 방식
프로그램 실행 시 모든 코드와 데이터를 메모리에 적재하지 않고,
실행 과정에서 실제로 필요한 페이지만 물리적 메모리로 가져옴
2) 프리페이징 (Pre-Paging)
프로그램 실행에 앞서 예상되는 페이지를 미리 메모리에 적재
프로그램 메모리 접근 패턴을 분석, 곧 접근될 것으로 예상되는 페이지 미리 적재
특징 | 디멘드 페이징 | 프리페이징 |
적재 시점 | 실제 접근 시 적재 | 예상 접근 전 미리 적재 |
장점 | 초기 메모리 사용량 감소, 효율적 메모리관리 | 페이지 폴트 감소, 실행 성능 향상 |
단점 | 초기 페이지 폴트 발생 가능 | 불필요한 페이지 적재로 자원 낭비 가능 |
페이징 (Paging) 기법
메모리 관리를 위한 비연속 할당 방식 중 하나, 큰 메모리 관리 문제를 작고 관리하기 쉬운 부분으로 나누어 해결하는 전략
가상 메모리를 물리 메모리에 적절히 매핑하여,
프로세스가 연속적인 메모리 공간을 요구하지 않고도 실행될 수 있도록 하는 메모리 관리 기법
물리 메모리를 일정한 크기인 `Frame`으로 나누고, 가상 메모리를 Frame과 동일한 크기의 `Page`로 나눔
페이지: 가상 메모리를 일정한 크기로 나눈 블록
프레임: 물리 메모리를 일정한 크기로 나눈 블록
- 각 페이지 (프레임)는 연속적이지 않은 공간에 존재 가능
- 프로세스마다 각자의 페이지 테이블 가짐
- 외부 단편화가 발생하지 않음 ∵ page size = frame size
내부 단편화 가 발생할 수 있다는 문제점
내부 단편화 ❓
일정한 크기로 자르는데 딱 맞게 잘리지 않아서 내부에서 메모리가 남는 문제
페이지 크기 10KB, 프로세스 크기 107KB
10KB 씩 분할하면 마지막 페이지 크기는 7KB가 되므로 3KB가 남음
페이지 테이블
- 페이지 테이블은 각 프로세스마다 독립적으로 존재
- RAM에 위치하며, 각 가상 페이지가 어느 물리 프레임에 매핑돼 있는지 저장하는 테이블
- 물리적으로는 분산되어 저장돼 있더라도, CPU 입장에서 바라본 논리 주소는 연속적으로 보임
∵ 페이지 테이블만 따라가면 되니까
운영체제는 페이지 테이블의 위치를 추적하기 위해 `PTBR` 사용
PTBR (Page Table Based Register) ❓
각 프로세스 페이지 테이블이 적재돼 있는 주소 저장, 이를 통해 CPU가 페이지 테이블에 접근
페이지 테이블의 역할
- 가상 페이지 번호 (VPN) → 물리 프레임 번호(PFN) 매핑
- 프로세스가 가상 주소 참조, 해당 주소에 대한 페이지 번호 추출
- 페이지 테이블 조회, 해당 페이지가 어느 물리 프레임에 매핑됐는지 확인
- 변환된 물리 주소를 통해 실제 메모리에 접근
- 페이지 부재 감지
- 페이지 테이블에 해당 페이지가 존재하지 않으면 페이지 부재 발생
- OS는 디스크에서 해당 페이지를 읽어와 메모리 적재 후, 페이지 테이블 업데이트
- 페이지 속성 관리
- 페이지 테이블에는 `매핑 정보 + 페이지 상태`를 나타내는 속성 정보 포함
페이지 테이블에 포함된 정보 (Page Table Entry, PTE)
Entry | 설명 |
프레임 번호 | 가상 페이지가 매핑된 물리 메모리 프레임 나타냄 |
유효성 비트 | 해당 페이지가 메모리에 있는지 여부 (0/1) |
보호 비트 | r/w/e 가능 여부 |
참조 비트 | 최근 해당 페이지 참조 여부 (page 교체 알고리즘에 활용) |
수정 비트 | 해당 페이지의 수정 여부 수정된 경우, 디스크에 기록 必 |
주소 변환 과정
프로그램이 적재된 상태에서의 주소 변환 과정
👉 프로그램 실행 中 발생하는 가상 주소를 실제 물리적 메모리 주소로 변환하는 과정 포함
1) 가상 주소 생성
CPU가 메모리에 접근하려 할 때 가상 주소 생성
📌 가상 주소의 구조
- `페이지 번호`: 해당 가상 주소가 속한 페이지 식별
- `오프셋`: 페이지 내에서 위치, 페이지 시작점부터 특정 데이터까지의 거리
2) 페이지 테이블 조회
CPU (정확히는 MMU)는 가상 주소에서 페이지 번호 추출, 이를 기반으로 페이지 테이블 조회
3) 물리 주소 계산
페이지 테이블에서 얻은 물리 페이지 번호 & 가상 주소의 오프셋 결합하여 최종 물리 주소 계산
해당 물리 주소는 실제 메모리에서 데이터를 읽거나 쓰는데 사용
4) 데이터 접근
결정된 물리 주소를 사용해 메모리에서 데이터 접근
세그멘테이션 (Segmentation) 기법
- 프로그램을 `논리적 단위` (코드, 데이터, 스택 등)로 분할하여 관리하는 기법
👉 다양한 크기를 가질 수 있음 - 가상 주소가 `(세그먼트 번호, 오프셋)`으로 나뉨. 이 주소를 통해 세그멘테이션 테이블 참조
- 세그먼트 시작 주소 & 크기 기반으로 물리 주소 계산
- `외부 단편화` 발생할 수 있음. 👉 빈 공간이 필요한 세그먼트를 담기에 부족할 수도
- 각 세그먼트가 논리적 & 가변적 크기를 가지므로 유연한 메모리 할당 가능
페이징 vs 세그멘테이션
특징 | 페이징 | 세그멘테이션 |
개념 | 고정 크기 블록 분할 (불변) | 논리적 단위 분할 (가변) |
단위 | 페이지 & 프레임 | 세그먼트 |
단편화 | 내부 단편화 | 외부 단편화 |
주요 장점 | 단편화 문제 효과적 해결 가상 메모리 관리 유리 |
논리적 구조에 맞는 메모리 할당 |
주요 단점 | 내부 단편화, 고정 크기로 유연성 ↓ | 외부 단편화, 메모리 관리 복잡 |
내부 단편화가 외부 단편화보다 더 나은 이유 ❓
외부 단편화는 시간이 지남에 따라 점차 심해질 수 있음.
메모리의 빈공간들이 불규칙적으로 남게 되는데, 이로 인해 메모리 자원이 있어도 효율적으로 사용X
내부 단편화는 페이지 크기를 적절히 조정하면 내부 단편화를 최소화 할 수 있음
내부 단편화는 외부 단편화보다 상대적으로 다루기 쉽고 예측 가능
MMU와 TLB
1) MMU (Memory Management Unit)
가상 주소를 물리 주소로 변환하는 역할을 담당하는 하드웨어 장치
MMU가 물리 주소를 확인하기 위해 `페이지 테이블`도 가야하고, `프레임`에서 데이터도 가져와야 함.
이렇게 Ram을 두 번 접근해야 하는데 더 효율적으로 일할 수는 없는가?
👉 이때 TLB를 사용
2) TLB (Translation Lookaside Buffer)
TLB는 주소 변환 속도를 높이기 위한 MMU의 캐시 역할을 하는 CPU (정확히는 MMU) 내부 고속 메모리
최근 변환한 가상 주소와 물리 주소 매핑 정보 저장 (페이지 테이블의 일부)
- `TLB Hit`: RAM 한 번 방문 (페이지 테이블 안 가고 바로 물리 주소 ㄱㄱ)
- `TLB Miss`: RAM 두 번 방문 ∵ 페이지 테이블 들러야 함
페이지 폴트 (Page Fault)
페이지 테이블 조회 과정 中 해당 가상 페이지가 현재 메모리에 적재되어 있지 않은 경우
즉, 가상 메모리에는 존재 하지만, RAM에는 현재 없는 데이터나 코드에 접근 하는 경우
페이지 폴트 처리 과정
- 페이지 폴트 예외가 발생, 현재 실행 중인 `프로세스 중단`
- 운영 체제의 페이지 폴트 핸들러 호출
- 커널 모드 전환 & 페이지 폴트 발생한 프로세스 처리 로직 시작
- 페이지 폴트 원인 분석
- 디스크에서 페이지 로딩
- 페이지가 디스크에 있는 경우, 해당 페이지를 디스크 → 메모리 로드
- 이 과정에서 디스크 I/O 발생 & 데이터가 메모리로 복사
- 페이지 테이블 갱신
- 페이지가 메모리에 로드된 후, 운영체제는 페이지 테이블 갱신,
해당 가상 주소가 올바른 물리적 주소 가리키도록 업데이트
- 페이지가 메모리에 로드된 후, 운영체제는 페이지 테이블 갱신,
- 기존 페이지 교체 (필요한 경우)
- 메모리가 부족하여 새로운 페이지를 로딩할 공간이 없다면, 다른 페이지를 스왑 아웃하여 디스크로 저장
페이지 교체 알고리즘 사용
- 메모리가 부족하여 새로운 페이지를 로딩할 공간이 없다면, 다른 페이지를 스왑 아웃하여 디스크로 저장
- 프로세스 재개
- 페이지 폴트가 처리된 후, 프로세스는 해당 페이지에 대한 정상 접근
- 페이지 폴트 처리 동안에는 일시적으로 성능 저하가 있을 수 있음
📌 스와핑 (Swapping)
물리적 메모리가 부족한 상태에서 디스크와 메모리 간 `전체 프로세스` 혹은 `페이지` 교환.
현대의 가상 메모리 시스템에서는 페이지 교체라는 방식으로 부분적 스와핑 이루어짐 (= 페이지 인, 페이지 아웃)
스래싱 (Thrashing)
프로세스가 실행되는 시간 < 페이지 교체 시간 → 성능 저하 문제
동시에 실행되는 프로세스의 수와 CPU 이용률이 비례하는 건 아님
CPU 이용률이 현저히 떨어지는 지점 = 스레싱이 발생하는 지점
스래싱은 왜 발생하는데 ❓
각 프로세스가 필요로 하는 최소한의 프레임 수가 보장되지 않아서 페이지 폴트 多
∴ 각 프로세스가 필요로 하는 최소한 프레임 수 파악 후, 적절한 프레임 할당
페이지 교체 방법
1) FIFO (First-In, First-Out)
`가장 먼저 메모리에 적재`된 페이지를 교체 대상으로 선택
구현이 간단, 메모리에 오래 머물렀다고 해서 해당 페이지의 중요도가 낮은 게 아니므로 중요 페이지 교체 가능성 有
2) LRU (Least Recently Used)
`가장 오랫동안 사용되지 않은` 페이지를 교체 대상으로 선택
최근의 접근 패턴 기반, FIFO에 비해 효율적인 교체 결정을 내릴수 있음.
But, 접근 시간을 기록하기 위한 추가적 메커니즘 必
3) LFU (Least Frequently Used)
`가장 적게 접근`된 페이지를 교체 대상으로 선택
페이지의 사용 빈도 기준, 단기간에 자주 사용되는 페이지 유지 가능
하지만, 초기에 자주 사용된 후 사용되지 않는 페이지가 메모리에 남을 수 있음
4) NUR (Not Used Recently) = Clock
각 페이지에 `사용 비트`를 두고, 페이지를 순환하며 사용 비트가 0인 페이지를 바로 교체 대상으로 선택
연속 메모리 할당 방식 (세그멘테이션 동일)
- 최초 적합 (First-Fit)
- 운영체제가 메모리 내의 빈 공간을 순서대로 검색하다가 적재할 수 있는 공간을 발견하면 그 안에 배치
- 검색 최소화 & 빠른 할당
- 최적 적합 (Best-Fit)
- 운영체제가 빈 공간을 모두 검색, 적재 가능한 가장 작은 공간에 할당
- 최악 적합 (Worst-Fit)
- 운영체제가 빈 공간을 모두 검색, 적재 가능한 가장 큰 공간에 할당
비연속 메모리 할당 방식
페이징 기법에서, 새로운 페이지를 메모리 어디에 적재할지 결정하는 방식
- 순차 할당 (Sequential Allocation) → 대부분 사용
- 메모리의 빈 프레임을 순서대로 채움
- 첫 번째 빈 프레임에 새로운 페이지 적재
- `프레임 테이블`을 사용하여 빈 프레임 추적
- 메모리가 연속적으로 사용되므로 캐시 효율이 높을 수 있음
- 랜덤 할당 (Random Allocation)
- 빈 프레임 중 무작위로 선택
- 특정 패턴 없이 고르게 배치 가능, 캐시 효율 떨어질 수도 있음
- 최적 프레임 선택 (Best Frame Selection)
- CPU 캐시 성능 등을 고려해 최적의 프레임 선택
- 고급 운영체제에서 사용, 메모리 접근 속도 최적화
📌 프레임 테이블
시스템 전체의 물리 메모리의 상태 관리,
각 프레임 사용 여부, 프레임 사용 프로세스 등 어떤 상태인지 추적하는 역할