시스템 · 서버핵심 · 19분 읽기

가상 메모리·페이지 변환·Swap과 메모리 부족

가상 주소가 실제 메모리에 연결되는 과정과 페이지 폴트·회수·Swap을 구분하고, free·vmstat·OOM 기록으로 메모리 문제를 해석합니다.

개념부터 찾아보기

정의·역할·동작 원리를 독립 페이지에서 확인하세요. 본문의 밑줄 용어에도 설명이 있습니다.

이 노트에서 설명할 수 있게 되는 것

  1. 가상 주소·페이지 테이블·물리 페이지와 TLB의 관계를 설명한다.
  2. 페이지 폴트가 디스크 접근이나 오류와 항상 같은 것은 아님을 구분한다.
  3. 메모리와 Swap 지표를 시간 변화와 함께 해석하고 성급한 설정 변경을 피한다.

01가상 메모리는 Swap보다 넓은 개념이다

  • 가 사용하는 주소는 일반적으로 그 의 가상 주소 공간 안에 있다.
    • 운영체제는 매핑과 접근 권한을 관리하고, CPU의 MMU가 메모리 접근 때 그 가상 주소를 로 변환한다.
    • A와 B에서 같은 숫자의 가상 주소를 사용해도 서로 다른 물리 메모리에 연결될 수 있다.
    • 이 분리는 주소 배치와 격리를 가능하게 한다.
  • Swap은 메모리 회수에 사용할 수 있는 저장 공간 또는 그 기능이다.
    • Swap을 꺼도 가상 주소와 페이지 테이블은 계속 사용된다.
    • 따라서 “RAM이 모자랄 때 디스크를 RAM으로 쓰는 것 = 의 전부”로 외우면 보호·공유·파일 매핑을 설명하지 못한다.
    • EMM386는 환경에서 EMS/UMB를 지원하는 메모리 관리자다.
    • 현대 운영체제의 가상 주소 공간·페이지 변환·보호 기능 전체를 가리키지는 않는다.

02메모리 접근과 페이지 폴트 처리 단계

  1. 가 자신의 주소 공간에서 읽기·쓰기·실행할 주소를 사용한다.
  2. 변환 정보가 있으면 활용한다. miss이면 가 정한 방식으로 페이지 테이블을 탐색한다.
  3. present 상태와 접근 권한을 확인한다. miss만으로 디스크 I/O가 발생하는 것은 아니다.
  4. 현재 접근을 완료할 수 없으면 운영체제가 페이지 폴트를 처리한다. 요청 시 할당··파일 또는 Swap 읽기·허용되지 않는 접근을 구분한다.
  5. 유효한 접근을 준비했다면 변환을 갱신하고 접근을 재개한다. 잘못된 주소나 권한 위반이면 SIGSEGV 등의 오류 처리로 이어질 수 있다.

03주소 공간에는 무엇이 놓이는가

  • 전형적인 설명에서는 실행 코드, 전역·정적 데이터, 동적 할당 영역, 호출 스택, 와 파일 매핑 등을 나눈다.
    • 실제 주소 배치와 성장 방향은 ·운영체제·런타임에 따라 다르다.
    • 각 영역의 역할을 이해하는 것이 한 장의 고정된 주소 그림을 모든 환경에 적용하는 것보다 중요하다.
  • 스택은 호출 상태와 지역 데이터 등에 쓰이지만 모든 지역 변수가 반드시 물리적인 스택 슬롯 하나에 놓이는 것은 아니다.
    • 최적화와 언어 구현이 배치를 바꿀 수 있다.
    • 동적 객체의 수명도 함수 종료와 일치하지 않는다.
    • 객체는 참조와 런타임 관리에 따라 살아남을 수 있고, 운영체제가 보는 의 메모리 영역과 언어가 보는 객체는 서로 다른 관찰 단위다.
관찰 단위설명하는 것혼동하기 쉬운 것
언어의 객체·변수값, 이름의 연결, 객체 수명변수 하나 = 페이지 하나가 아니다
의 가상 영역주소 범위, 용도, 접근 권한예약한 주소 범위 전체가 현재 RAM에 상주하지는 않는다
물리 페이지RAM의 실제 저장 단위공유되면 여러 매핑에서 참조할 수 있다
Swap 슬롯·파일 페이지RAM 밖에 보관하거나 다시 읽을 근거Swap 사용량만으로 현재 장애를 판정하지 않는다
원리 심화

04할당기·가상 주소 영역·실제 페이지의 세 경계

  • 언어의 객체 생성이나 malloc 요청이 매번 새 운영체제 매핑을 만드는 것은 아니다. 가 확보한 메모리를 나눠 재사용할 수 있다.
  • 의 주소 범위에는 읽기·쓰기·실행 권한과 파일 연결 여부 같은 속성이 있다. 주소 범위를 예약한 것과 해당 페이지가 RAM에 존재하는 것은 구분한다.
  • 요청 시 할당을 쓰는 환경에서는 접근 때 페이지 폴트로 실제 페이지가 준비될 수 있다. 가상 크기가 늘어난 순간에 RSS가 같은 양으로 늘어야 하는 것은 아니다.
  • 같은 파일의 읽기 전용 페이지를 여러 가 공유할 수 있다. private 매핑의 변경은 원본 파일의 공유 변경과 다르게 처리되며 가 관여할 수 있다.
  • 객체 참조가 사라지거나 free를 호출해도 가 공간을 보유하면 RSS가 바로 줄지 않을 수 있다. 해제 호출· 재사용·운영체제 반환을 다른 관측으로 본다.
  • 페이지 테이블·커널·파일 캐시와 에 집계되는 다른 사용량도 있다. RSS 하나만으로 호스트 전체와 사용량을 설명하지 않는다.

05페이지 번호와 오프셋으로 주소를 나누기

  • 페이지 방식에서는 가상 주소 공간과 물리 메모리를 일정 크기의 단위로 다룬다.
    • 4 KiB 페이지를 가정하면 페이지 안의 위치를 나타내는 오프셋은 12비트다.
    • 나머지 주소 부분으로 페이지 테이블의 매핑을 찾고, 얻은 물리 페이지 프레임 번호에 같은 오프셋을 붙인다.
    • 4 KiB는 흔한 기본값의 예시이며 시스템에 따라 다른 페이지 크기와 huge page도 사용한다.
  • 예를 들어 단순화한 가상 주소 0x12345에서 페이지 번호는 0x12, 오프셋은 0x345다.
    • 페이지 번호 0x12가 물리 프레임 0x8A에 매핑되었다면 는 0x8A345다.
    • 실제 CPU는 다단계 페이지 테이블 등 아키텍처별 구조를 사용하므로, 이 계산은 의 의미를 보여 주는 보충 예제다.
주소 계산
페이지 크기 = 4096 = 0x1000
가상 주소 = 0x12345
가상 페이지 번호 = 0x12345 // 0x1000 = 0x12
페이지 오프셋 = 0x12345 % 0x1000 = 0x345
가정한 매핑: VPN 0x12 → PFN 0x8A
물리 주소 = 0x8A × 0x1000 + 0x345 = 0x8A345

실제 시스템에서 읽어 온 주소가 아닌, 계산 과정을 검산할 수 있도록 만든 예제다.

06TLB 조회와 페이지 테이블 검사

  • 주소를 참조할 때마다 긴 페이지 테이블 탐색을 반복하면 비용이 커진다.
    • 는 최근 주소 변환과 관련 권한 정보를 빠르게 재사용하기 위한 CPU의 캐시다.
    • hit이면 캐시된 변환을 활용하고, miss이면 가 정한 방식으로 페이지 테이블을 찾아 변환을 채운다.
    • miss 자체는 디스크를 읽는다는 뜻이 아니다.
  • 매핑에는 단순한 위치뿐 아니라 present 여부와 읽기·쓰기·실행, 사용자·커널 접근 등 보호 정보가 연결된다.
    • 주소가 존재하더라도 허용하지 않는 쓰기나 실행이면 예외가 발생할 수 있다.
    • 운영체제가 매핑을 바꿀 때 오래된 변환을 계속 쓰지 않도록 무효화가 필요하다.
    • 여러 CPU에서 같은 주소 공간을 실행하는 경우 관련 CPU 사이의 조정도 필요하다.

07페이지 폴트: 정상 처리와 잘못된 접근을 구별하기

  • CPU가 현재 상태로 메모리 접근을 완료하지 못하면 페이지 폴트 예외를 통해 운영체제에 처리를 넘길 수 있다.
    • 운영체제는 유효한 주소의 아직 준비되지 않은 페이지인지, Copy-on-Write를 위한 쓰기인지, Swap에서 다시 읽어야 하는지, 아예 허용하지 않는 접근인지를 구분한다.
    • 모든 페이지 폴트가 버그이거나 디스크 I/O인 것은 아니다.
  • 요청 시점에 처음 사용하는 에는 새 페이지나 초기화된 페이지를 준비할 수 있다.
    • 뒤 부모·자식이 페이지를 읽기 전용으로 공유하다 한쪽이 수정하면 필요한 페이지를 복사하고 매핑을 바꾸는 Copy-on-Write 처리를 할 수 있다.
    • 공유하던 데이터가 실제로 수정될 때 비용을 부담하는 것이다.
  • 파일이나 Swap에서 데이터를 읽기 위해 I/O가 필요한 major fault와 I/O 없이 해결되는 minor fault를 나누어 관찰한다.
    • 접근이 주소 영역이나 권한 규칙에 맞지 않으면 에 SIGSEGV 등으로 전달될 수 있다.
    • 특정 fault 수치 하나를 곧바로 공격·장애로 해석하지 않고 어떤 작업 중 발생했는지 본다.
예제로 추적

08COW 한 번이 RSS·PSS와 실제 점유를 바꾸는 계산

  1. 부모·자식이 4KiB 데이터 페이지 3개를 공유한다고 가정한다. 스택·페이지 테이블·다른 매핑은 계산에서 제외한 학습 모델이다.
  2. 각 RSS는 12KiB다. 두 가 반씩 부담한다고 계산한 PSS는 각각 6KiB이고, 실제 데이터 페이지는 합계 12KiB다.
  3. 자식이 공유 페이지 하나에 쓰면 로 별도 페이지가 준비된다. 부모는 기존 페이지를, 자식은 복사한 페이지를 사용한다.
  4. 각 RSS는 여전히 12KiB다. 각 PSS는 전용 4KiB + 공유 8KiB의 절반인 4KiB = 8KiB다. 실제 데이터 페이지는 16KiB로 늘었다.
  5. 자식 전용 페이지가 해제되고 부모만 원래 3페이지를 참조하면 부모 RSS·PSS는 각각 12KiB가 된다. PSS 증가는 부모가 새 페이지를 할당했다는 뜻만은 아니다.
  6. /proc/PID/smaps의 매핑별 Rss·Pss·Shared/Private 값을 시점별로 비교한다. 실제 시스템은 페이지 크기·추가 매핑·공유 수가 달라 모델과 정확히 같지 않을 수 있다.
시점부모 RSS/PSS자식 RSS/PSS실제 데이터 페이지
3페이지 공유12 / 6 KiB12 / 6 KiB12KiB
자식이 1페이지 변경12 / 8 KiB12 / 8 KiB16KiB
자식 종료12 / 12 KiB없음12KiB

09회수할 페이지: 파일 캐시와 익명 메모리

  • 는 남는 메모리를 등에 활용한다.
    • 파일에서 읽었고 수정되지 않은 깨끗한 페이지는 원본 파일에서 다시 읽을 수 있으므로 회수 대상이 될 수 있다.
    • 수정된 파일 페이지는 해당 내용을 보존하기 위해 저장 장치로 쓰는 처리가 필요하다.
    • 캐시가 크다는 사실만으로 메모리 누수라고 보지 않는 이유다.
  • 일반적인 는 대응하는 원본 파일이 없으므로 내용을 버렸다가 파일에서 다시 읽을 수 없다.
    • 운영체제는 조건에 따라 Swap으로 내보내거나, 압축 메모리 등 구성된 기능을 활용할 수 있다.
    • Swap이 없다면 선택 가능한 회수 경로가 달라진다.
    • 전체 RAM이 남아 있어도 ·서비스의 메모리 제한 때문에 별도의 부족 상황이 생길 수 있다.
  • 작업에 필요한 페이지 집합이 가용 메모리보다 커서 반복적으로 내보내고 다시 읽는 상태에서는 처리 시간의 많은 부분을 메모리 회수와 I/O에 사용한다.
    • 이를 단순히 “Swap을 더 만들면 해결”로 접근하면 원인인 작업량·제한·누수·비효율적 캐시를 놓칠 수 있다.

10free와 vmstat를 함께 읽는 순서

  • free의 free는 완전히 사용하지 않는 메모리이고, available은 새 작업에 사용할 수 있을 것으로 추정되는 양이다.
    • 둘은 같은 값이 아니다.
    • buff/cache와 reclaimable 메모리 등을 고려해야 한다.
    • Swap used가 남아 있어도 현재 활발한 Swap I/O가 발생한다는 뜻은 아니다.
    • 이전에 밀려난 덜 쓰는 페이지가 그대로 남을 수 있다.
  • vmstat의 si/so를 일정 간격으로 읽어 Swap 유입·유출 추세를 보고, 실행 대기·I/O 대기와 서비스 응답 지연을 함께 확인한다.
    • 첫 보고 행은 대개 부팅 이후 평균이므로 이후 구간 보고와 구분한다.
    • 페이지 폴트· 상주량·커널 로그까지 연결해야 압박을 받는 주체를 좁힐 수 있다.
관측가능한 해석추가로 확인할 근거
free가 낮고 available이 충분파일 캐시 활용일 수 있음서비스 지연, available 추세
Swap used만 높고 si/so가 조용함현재 교환이 활발하다고 단정 불가일정 기간의 I/O와 메모리 사용
si/so와 지연이 함께 지속 상승메모리 압박·working set 초과 가능 RSS/PSS, 제한, 스토리지 지연
특정 서비스만 OOM 종료 제한 등 국소 부족 가능서비스 제한과 커널· 기록
조회
free -h
swapon --show --bytes
cat /proc/swaps
vmstat 1 5
cat /proc/meminfo
cat /proc/pressure/memory

학습 환경에서 상태를 읽는 예제다. 출력 항목과 단위는 도구 버전을 확인하며, pressure 정보는 커널 지원과 설정에 따라 제공된다. 사이트 작성 중 사용자 PC의 메모리 설정을 바꾸거나 이 실습을 실행하지 않았다.

LEARN THROUGH PRACTICE

inxi의 메모리·Swap 요약을 커널 통계와 연결하기

설치 용량·커널이 이용할 용량·현재 사용량을 구별하고, Swap 사용량 0이 의미하는 범위를 확인한다.

실습 구성과 전제

  • 화면은 게스트의 이며 inxi 3.3.33 출력을 보여 준다.
  • inxi 요약 두 장은 서로 다른 시점이다. 작은 사용량 차이를 곧바로 누수나 성능 문제로 판정하지 않는다.
  1. 도구의 필드 정의부터 맞춘다

    • inxi의 total은 설치된 RAM 규모, available은 예약 영역 등을 뺀 커널 사용 가능 총량이다. free의 available이나 /proc/meminfo의 MemAvailable과 같은 뜻이 아니다.
    • 화면의 사용률은 inxi available을 기준으로 한다. 설치 용량 4 GiB를 분모로 임의 계산하면 표시값과 다를 수 있다.
    5/26 - php, mariaDB · 실습·개념 참고 화면 2원본 크기로 보기 ↗
    • Info Memory 행은 total 4 GiB, available 3.54 GiB, used 627.8 MiB (17.3%)다.
    • Swap 행에는 type partition, size 3.91 GiB, used 0 KiB와 /dev/dm-1이 보인다.
    확인 기준

    RAM 용량과 Swap 파티션 크기를 서로 다른 자원으로 기록한다.

  2. 한 시점의 사용량과 시간에 따른 압력을 분리한다

    • 다른 요약은 629.8 MiB/3.54 GiB와 17.4%를 보여 준다. ·캐시·관측 시각이 바뀌면 사용량도 변할 수 있다.
    • 누수나 압력 여부는 시간에 따른 추세, 점유, 회수·입출력 지표와 함께 판단한다. 단일 전체 사용률만으로 특정 가 원인이라고 할 수 없다.
    bash
    free -h
    vmstat 1 5
    cat /proc/meminfo

    현 환경에서 메모리 가용 추정치와 시간 구간별 활동을 비교하는 조회 예시다.

    5/26 - php, mariaDB · 실습·개념 참고 화면 1원본 크기로 보기 ↗
    • 간략 출력은 Mem 629.8 MiB/3.54 GiB (17.4%)로 표기된다.
    • Uptime과 프로세스 수가 상세 화면과 달라 같은 순간의 완전한 반복 측정으로 볼 수 없다.
    확인 기준

    vmstat 첫 줄과 후속 구간의 의미를 구분하고 si·so 및 실행 대기·I/O 지표를 함께 읽는다.

  3. Swap 0과 Swap 비활성을 구별한다

    • 사용량 0은 그때 Swap에 사용 중인 양이 없다는 뜻이다. 구성·활성화 여부는 활성 Swap 목록으로 별도 확인한다.
    • Swap 사용량이 존재하는 것만으로 현재 심한 스와핑이라고 할 수도 없다. 실제 swap-in/out 활동과 메모리 압력의 동시 관측이 필요하다.
    bash
    swapon --show
    cat /proc/swaps
    cat /proc/pressure/memory

    활성 Swap과 지원되는 커널의 메모리 압력을 읽는다. 경로는 커널 설정에 따라 없을 수 있다.

    확인 기준

    활성 목록, 사용량, 구간별 입출력을 서로 다른 항목으로 기록한다. 캡처에는 Swap 변경·비활성화 결과가 없다.

실습에서 확인한 동작 원리

  • 같은 available이라는 이름도 도구에 따라 정의가 다르므로 필드의 분모와 단위를 확인한다.
  • ·현재 RAM 점유·Swap 구성·현재 은 구별해서 관측한다.
동작·명령 참고 문서

11Swap 파일·파티션과 swappiness의 의미

  • Swap은 전용 파티션이나 지원되는 파일 시스템의 파일 등으로 제공할 수 있다.
    • 파일을 사용할 때는 해당 파일 시스템의 hole·Copy-on-Write·스냅샷 제약을 확인해야 한다.
    • 모든 파일 시스템에서 같은 fallocate 절차를 그대로 적용할 수 있다고 가정하면 안 된다.
    • 권한과 영구 설정도 함께 관리해야 하지만, 이미 운영 중인 저장 영역을 잘못 초기화하는 위험 때문에 개념 이해와 실제 변경 작업은 구분한다.
  • 는 RAM이 몇 퍼센트 찼을 때 Swap을 켜는 임계값이 아니다.
    • 회수 과정에서 익명 페이지와 파일 기반 페이지의 비용을 비교하는 정책 매개변수다.
    • 최적값은 저장 장치·압축 Swap·작업 특성에 따라 달라지므로 “항상 낮을수록 좋다”는 규칙으로 외우지 않는다.
    • 변경 전후의 지연과 I/O를 비교해야 의미가 있다.
  • swapoff는 사용 중인 Swap 데이터를 다시 처리해야 하므로 여유 메모리와 다른 회수 자원이 부족하면 실패하거나 큰 압박을 만들 수 있다.
    • 사용량 숫자를 0으로 만들기 위해 습관적으로 수행할 작업이 아니다.
    • RAM을 늘리거나 불필요한 작업을 줄이는 조치와 달리, 문제의 원인을 제거하지 않을 수 있다.

12OOM·누수·프로세스 메모리를 구분하기

  • 주소 공간 크기(VSZ)가 크다고 그만큼의 물리 RAM을 독점하고 있는 것은 아니다.
    • RSS는 현재 상주하는 페이지를 보지만 공유 페이지를 여러 에서 중복 집계할 수 있다.
    • PSS는 공유분을 나누어 계산해 기여도를 이해하는 데 도움을 준다.
    • 어느 지표를 더했는지 모르면 시스템 전체와 합계가 다르다는 이유로 오류라고 판단하기 쉽다.
  • 메모리 누수는 필요가 끝난 자원을 계속 유지하여 회수되지 않는 현상이며, 증가 추세와 작업량의 관계를 조사한다.
    • 정상 캐시·배치 작업의 일시적 최대 사용량과 구분해야 한다.
    • OOM은 전체 시스템이나 제한된 에서 회수가 충분하지 않은 상황과 연결될 수 있다.
    • 종료 시각, 대상 PID·서비스, 제한값, 당시의 부하와 커널 기록을 함께 보존한다.
  • 객체 → 가상 주소 매핑 → 상주 페이지 → 회수·Swap → 작업 지연의 순서로 연결하면, 프로그램 수정이 필요한지 서비스 제한 조정이 필요한지 저장 장치나 용량 문제인지 판단할 근거가 생긴다.
검증·예외

13호스트는 여유가 있는데 컨테이너가 느리거나 종료되는 이유

  • 먼저 가 속한 과 상위 제한을 확인한다. 호스트의 available 메모리가 많아도 해당 그룹의 한계에 먼저 도달할 수 있다.
  • 이 경계를 넘으면 할당·회수 과정에서 지연과 회수 압력이 생길 수 있다. high 초과 자체가 OOM killer 실행을 의미하지는 않는다.
  • 메모리 상한에서 필요한 회수에 실패하면 해당 의 OOM이 발생할 수 있다. 설정값·memory.current·memory.events와 실제 종료 시점을 연결한다.
  • /proc/pressure/memory의 some은 일부 작업이 메모리 자원 때문에 정체한 시간, full은 모든 비유휴 작업이 동시에 정체한 시간의 비율이다. 단순 메모리 사용률이 아니다.
  • 가상 관측에서 some total이 10초 동안 2,000,000µs 증가하면 해당 구간의 정체 비율은 20%다. avg10 같은 추세 평균과 이 직접 구간 계산을 동일한 값이라고 요구하지 않는다.
  • RSS 증가·page fault·swap 입출력·· 사건·요청 지연을 같은 시간축에 놓는다. OOM만 기다리지 말고 회수 지연으로 이미 서비스가 느려진 상태도 찾는다.
READ · OBSERVE · CONNECT

함께 보는 학습 자료

아래 공식 자료를 본문의 개념·예제와 함께 읽어 보세요. 자료별로 확인할 위치와 관찰할 내용을 적었습니다.

공식 가이드

cgroup v2의 memory.high·max·events

Memory Interface Files에서 memory.high와 memory.max를 나란히 읽고 memory.events의 high·oom·oom_kill을 연결한다. Swap 사용량과 메모리 압박, OOM 종료를 별도 관측으로 구별하는 경로다.

읽으면서 확인할 것
  • high 초과가 회수·제한으로 이어지는 조건
  • max 한계에서 회수가 불가능한 경우의 OOM 범위
  • memory.events가 단순 사용 바이트가 아닌 사건 횟수인 점
학습 확인

이해했는지 확인하기

  • Swap이 0이어도 가상 메모리를 사용하는 이유를 설명할 수 있는가?
  • 4 KiB 페이지에서 주소 0x12345의 페이지 번호와 오프셋을 계산할 수 있는가?
  • TLB miss·minor fault·major fault·잘못된 접근을 구분할 수 있는가?
  • Swap used 하나만으로 장애라고 단정하지 않고 추가 관측을 고를 수 있는가?

함께 확인할 공식 자료