(참고: Fastcampus 강의, 강민철의 인공지능 시대 필수 컴퓨터 공학 지식)

5. 가상 메모리 관리

Contents

  1. 페이징 & 페이지 테이블
  2. 가상 메모리
  3. 요구 페이징 & 스래싱
  4. 페이지 교체 알고리즘
  5. copy-on-write
  6. 캐시 메모리 정책


(1) 페이징 & 페이지 테이블

a) 스와핑

프로세스를 보조기억장치의 일부 영역으로 쫓아내고,

당장 필요한 프로세스를 적재하는 메모리 관리 기법


용어

  • 스왑 아웃 (swap-out): 프로세스를 보조기억장치의 일부 영역으로 쫓아내는 것
  • 스왑 인 (swap-in): 스왑 아웃된 프로세스를 메모리에 적재하는 것
  • 스왑 영역: 스왑 아웃된 프로세스가 적재되는 보조기억장치 영역

figure2


b) 연속 메모리 할당

프로세스를 메모리에 연속적으로 배치하는 방식

figure2


부작용: 외부 단편화

  • 빈 공간이 생기는 메모리 낭비 현상!

figure2


c) 페이징

외부 단편화를 해결하는 방법은?

\(\rightarrow\) 페이징 (paging) = 메모리와 프로세스를 일정 단위로 자르자!

figure2


상세 방식

  • 물리 메모리를 “프레임 (frame)”이라는 일정한 크기로 나누고
  • 프로세스를 “페이지 (page)”라는 일정한 크기로 나눈 뒤
  • “페이지를 프레임에 매핑”하는 메모리 관리 방식

figure2


d) 페이지 인 & 페이지 아웃

figure2


(2) 가상 메모리

프로세스의 일부만을 적재하여, “실제 물리 메모리보다 큰 프로세스”를 실행하는 기술!

페이징은 가장 대표적인 가상메모리 관리 기법

figure2


a) 가상메모리 - 비유 (feat. ChatGPT)

너가 1,000페이지짜리 책을 읽는다고 해보자. 근데 손에 들 수 있는 건 100페이지짜리 얇은 노트뿐이야.
그래서 필요한 부분만 "복사해서 노트에 옮기고" 읽는 거지. 
나중에 다른 부분이 필요하면, "다시 교체해서" 읽고.
이렇게 하면 책 전체가 손에 없어도, 읽는 데는 문제 없어!
  • 디스크(책 전체)에 프로그램 전체가 있고
  • RAM(작은 노트)에는 실행에 필요한 일부분만 임시로 적재


이게 어떻게 가능??

운영체제가 페이지 단위로 메모리를 나눠서 관리하고,

  • 실행 중에 필요한 페이지만 메모리에 로딩해 줘
  • 필요한데 메모리에 없으면 → 페이지 폴트(page fault) 발생 → 디스크에서 RAM으로 불러옴

이걸 페이지 교체(page replacement) 전략으로 자동 처리해 줘


b) 페이지 테이블

어떤 페이지 & 어떤 프레임 매핑 되었는지 어떻게 암?

\(\rightarrow\) via “페이지 테이블”

  • 프레임과 페이지의 매핑 정보를 담고 있는 테이블

figure2


“프로세스”마다 페이지 테이블을 가지고 있음.

figure2


c) 페이지 테이블 베이스 레지스터 (PTBR)

페이지 테이블이 어디에 있는지를 CPU가 알 수 있게 해주는 레지스터

figure2


페이지 테이블은 어디에 있는 것이 좋을까?

  • 후보 1) 메모리

    \(\rightarrow\) No! 메모리 접근 시간 2배 필요

    • (1) 페이지 테이블 접근
    • (2) 프레임 접근
  • 후보 2) 캐시 메모리

    \(\rightarrow\) Yes! TLB (Translation Look-aside Buffer)

    • 페이지 테이블의 캐시 메모리

figure2


[페이지 테이블 내 정보]

유효 비트 (valid bit)

  • 접근하려는 페이지가 “보조기억 장치”에 있는지, “메모리”에 있는지
  • 1 = 메모리에 적재되어 있음 O
  • 0 = 메모리에 적재되어 있지 X
  • If 적재 X (즉, 보조기억장치에 있는 경우)? => 페이지 폴트 (page fault)
    • Step 1) 작업 내역 백업
    • Step 2) Page fault 루틴 실행 - 접근하려는 페이지 적재
    • Step 3) 유효비트 0 \(\rightarrow\) 1로 변경
    • Step 4) 접근하려는 페이지 접근


보호 비트 (protection bit)

  • r/w/x를 통해 읽기/쓰기/실행 등의 구분


참조 비트 (reference bit)

  • 접근한 적이 있는 페이지인지 구분


수정 비트 (modify bit / dirty bit)

  • 쓰기 작업을 한 적이 있는 페이지인지


figure2


d) 계층적 페이징

페이지 테이블 크기를 줄이기 위해!

figure2


(3) 요구 페이징 & 스래싱

a) 요구 페이징

처음부터 모든 페이지를 적재하지 않고, 페이지 폴트가 발생하면 그 때 페이지를 적재한다!


순수 요구 페이징

  • (처음) 아무 페이지도 적재 X
  • 첫 명령어 실행부터 페이지 폴트가 발생할 것!
  • 적당한 페이지가 적재된 이후부터는, 페이지 폴트가 감소할 것!


페이지 폴트가 적게 발생하는 방법은?

  • (근본적으로는) 물리 메모리가 크면 됨
    • 프레임이 \(\infty\) \(\rightarrow\) 무한히 많은 페이지 적재 가능
    • 프레임이 1개 \(\rightarrow\) 페이지 접근할 때마다 페이지 폴트가 발생


b) 스래싱

프로세스 실행 시간보다, “페이징에 더 많은 시간이 소요”되는 문제

( Due to 지나친 페이지 폴트! )

  • 동시에 실행되는 프로세스 수를 늘린다고해서, 반드시 CPU 이용률이 비례해서 높아지는 것이 아닌 이유임

figure2


c) 페이지 교체 알고리즘

현실적으로, 물리적인 메모리 (프레임)은 무한하지 않음.

그렇다면, 어떻게 페이지 폴트 횟수를 줄일 수 있을까?

\(\rightarrow\) 페이지 교체 알고리즘! (뒤에서 다룰 것)

  • 보조기억장치로 내보낼 페이지 & 메모리에 적재할 페이지를 잘 선별하면 된다.


(4) 페이지 교체 알고리즘

메모리에 적재된 페이지 중, 페이지-아웃시킬 페이지를 선정하는 방법

  • 좋은 페이지 교체 알고리즘 = 페이지 폴트를 “적게 일으키는” 알고리즘


페이지 참조열

  • CPU가 참조하는 페이지 중 연속된 페이지를 생략한 페이지열
  • Example)
참조한 페이지: 2 2 2 3 5 5 5 3 3 7
페이지 참조열: 2 3 5 3 7


페이지 교체 알고리즘의 예시

  • (1) FIFO
  • (2) 2차 기회 FIFO
  • (3) 최적
  • (4) LRU


(5) copy-on-write

핵심: 복사는 나중에! 처음에는 공유하고, 진짜 수정하려고 할 때만 복사하는 기술!


비유 (feat. ChatGPT)

너랑 친구가 같은 문서를 읽고 있다고 해보자.
둘 다 "복사하지 않고" 같은 문서를 보고 있어 (공유 중).

그런데 친구가 갑자기 내용을 수정하려고 하면?
=> 그 순간 "자기만의 복사본을 만들어서 수정"해.


fork

  • 대표적으로 fork() 시스템 호출에서 사용

    • fork(): 부모 프로세스를 복제해서 자식 프로세스를 만듬
  • 실제로는 메모리를 복사하지 않고, 부모와 자식이 같은 페이지를 공유

    \(\rightarrow\) 둘 중 누가 수정하려고 하면 그때 진짜 복사


장점

  • 메모리 절약: 처음엔 복사하지 않으니 자원 아낌
  • 속도 향상: 필요할 때만 복사하니까 효율적


Summary

항목 설명
언제 복사? 수정하려고 할 때 (write 시점)
초기 상태 페이지를 공유 (읽기 전용)
목적 성능 최적화, 메모리 절약
사용 예 fork(), 가상 메모리 시스템, 일부 STL 컨테이너(C++)


figure2

figure2


(6) 캐시 메모리 정책

a) 캐시 메모리 복습

  • CPU와 메모리 간의 속도 차를 극복하기 위해

  • CPU와 메모리 사이에 위치

    ( CPU에서 사용할 법한 정보를 미리 가져와 저장 )

  • 레지스터보다 용량이 크고, 메모리보다 빠른 SRAM 기반

  • 종류: L1,L2,L3 cache

  • 캐시 히트 & 캐시 미스


b) 참조 지역성의 원리

캐시 메모리에는, “CPU가 자주 사용할 법한 내용”을 담는다.

Q) 자주 사용할 법한 내용은?

A) 참조 지역성의 원리

  • 시간 지역성: CPU는 최근에 접근했던 메모리 공간에 다시 접근하려는 경향
  • 공간 지역성: CPU는 접근한 메모리 공간 근처를 접근하려는 경향


c) 캐시 메모리 쓰기 정책: 데이터 일관성

캐시 메모리에 데이터를 새롭게 쓰는 상황!

\(\rightarrow\) 캐시 메모리 & 메모리 간의 “데이터 일관성”은 필수적이다!


데이터 일관성이 깨지는 case:

figure2


d) 즉시 쓰기 & 지연 쓰기

즉시 쓰기 (write-through)

  • 캐시 메모리 & 메모리에 “동시에” 쓰기

  • 메모리를 항상 최신 상태로 유지!

  • 다만, 데이터를 쓸 때마다 메모리를 참조해야함.

    \(\rightarrow\) 버스의 사용 시간 & 쓰기 시간이 늘어나게 됨

figure2


지연 쓰기 (write-back)

  • 캐시 메모리에만 써두었다가, 나중에 한번에 반영!

  • 장점: 메모리 접근 횟수를 줄일 수 있음!

    ( “즉시 쓰기” 방식보다 빠르다 )

  • 한계점: 메모리와 캐시 메모리간의 일관성이 깨질 수도!

figure2


e) 캐시 신선도

캐시에 저장된 데이터가 실제 원본 데이터와 얼마나 최신 상태인지

즉, “캐시된 정보가 아직 유효한가?”를 판단하는 개념


캐시 신선도 유지하는 방법들

방법 설명
TTL (Time-To-Live) 일정 시간 지나면 캐시를 자동으로 무효화함
LRU (Least Recently Used) 가장 오래 안 쓰인 캐시부터 제거
캐시 무효화(Invalidation) 원본이 바뀌면 캐시도 강제로 업데이트함

Categories: ,

Updated: