운영체제 용어 사전
가상 메모리demand paging · major fault · minor fault

페이지 폴트

접근한 페이지가 물리 메모리에 없을 때 발생하는 예외. 디스크를 읽는 major가 진짜 비용이다.

접근하려는 페이지가 물리 메모리에 없을 때 발생하는 예외.

처리 과정

  • ① CPU 가 주소 변환을 시도한다 → 페이지 테이블에 '없음' 표시
  • ② 페이지 폴트 예외가 발생한다 → 커널로 진입
  • ③ 커널이 판단한다
    • 정당한 접근인가? 아니면 → SIGSEGV (프로그램 종료)
  • ④ 빈 프레임을 확보한다 (없으면 페이지 교체)
  • ⑤ 필요하면 디스크에서 읽어 온다
  • ⑥ 페이지 테이블을 갱신하고 그 명령을 '다시 실행' 한다

⑥이 중요하다 — 실패한 명령이 처음부터 다시 실행되므로 프로그램은 폴트가 있었는지도 모른다.

두 종류를 구분한다

minor fault (soft)

  • 디스크를 읽지 않는다
  • 이미 메모리에 있는 페이지(페이지 캐시 · 공유 라이브러리)를 매핑만 한다
  • copy-on-write 로 복사한다
  • 처음 접근하는 힙 페이지에 0 채운 프레임을 준다
  • 빠르다 (마이크로초)

major fault (hard)

  • 디스크에서 읽어 와야 한다
  • 느리다 (밀리초 — 만 배 차이)
  • 이게 많으면 성능이 무너진다
ps -o min_flt,maj_flt,cmd -p <pid>
/usr/bin/time -v ./app | grep -i fault
#   Major (requiring I/O) page faults: 12
#   Minor (reclaiming a frame) page faults: 45231

vmstat 1     # si/so 열이 스왑 in/out — 0이 아니면 경고

minor가 많은 건 정상이다. major가 지속적으로 발생하면 메모리가 부족하다는 뜻이다.

demand paging — 필요할 때만 가져온다

프로그램을 시작할 때 전부 메모리에 올리지 않는다

  • 실제로 접근하는 페이지만 그때그때 올린다

효과

  • 시작이 빠르다
  • 물리 메모리보다 큰 프로그램을 돌릴 수 있다
  • 안 쓰는 코드(에러 처리 경로 등)는 영영 안 올라온다
// mmap 은 이 성질을 그대로 활용한다
void *p = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
// 파일을 '매핑' 만 한다. 실제 읽기는 접근하는 순간 페이지 폴트로 일어난다

면접 함정

  • "페이지 폴트는 에러다" → 정상적인 메커니즘이다. 잘못된 접근일 때만 SIGSEGV가 된다.
  • "페이지 폴트가 많으면 문제" → minor는 정상이다. major를 봐야 한다.

첫 접근 비용

char *p = malloc(1UL << 30);   // 1GB 할당 — 거의 즉시 끝난다
// 아직 물리 메모리를 안 받았다. 주소 공간만 예약됐다

memset(p, 0, 1UL << 30);       // 여기서 페이지 폴트가 26만 번 (4KB 기준)
// 이때 실제로 물리 메모리가 붙는다

"할당은 빠른데 처음 쓸 때 느리다" 가 이 구조에서 나온다. 벤치마크에서 워밍업이 필요한 이유 중 하나다.

mmap(..., MAP_POPULATE, ...);  // 미리 물리 페이지를 붙여 둔다
mlock(p, size);                 // 스왑 아웃되지 않게 고정한다

힙이 늘어나는 과정

  • malloc 이 작은 크기면 → 미리 받아 둔 힙에서 잘라 준다 (시스템 콜 없음)
  • 힙이 모자라면 — → brk 나 mmap 으로 주소 공간을 더 받는다
  • 실제 물리 메모리는 — → 그 주소를 처음 건드릴 때 페이지 폴트로 붙는다

세 단계가 분리돼 있어서 "free 는 늘었는데 RSS 는 안 줄어드는" 현상이 생긴다

  • free 한 메모리를 할당자가 OS 에 즉시 반납하지 않고 재사용을 위해 쥐고 있다

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 가상 메모리 — 페이징·TLB·페이지 폴트