CS Insights

리눅스 커널의 페이지 폴트 예외 처리 구조와 디맨드 페이징의 본질

리눅스 커널의 페이지 폴트 예외 처리 구조와 디맨드 페이징의 본질
기술 면접관으로 참여하면서 가장 많이 질문하지만 가장 답변을 못 듣는 주제입니다. 개발자라면 꼭 알아야 할 내용을 제 주관적인 시각으로 풀어봤습니다. 현대의 응용 프로그램은 시스템에 장착된 물리 메모리 크기를 초과하는 가상 주소 공간을 할당받았다고 착각하며 동작합니다. 이 환상을 지탱하는 물리적 토대가 하드웨어 MMU(메모리 관리 장치) 시스템이며, 환상의 연출자가 바로 운영체제의 페이지 폴트(Page Fault) 예외 처리 핸들러입니다. 프로그램이 새로운 메모리 공간을 요청하는 malloc 등의 래퍼 함수를 호출하더라도, 리눅스 커널은 실제 물리적 RAM을 해당 시점에 즉시 할당하지 않습니다. 커널은 그저 가상 메모리 관리 구역인 VMA(Virtual Memory Area) 구조체에 메타 정보를 입력하여 주소의 권한만을 활성화하는 지연 할당(Demand Paging) 기법을 사용합니다. 이는 실행되지 않을 코드나 읽지 않을 데이터 영역에 메모리를 즉각 소모하는 비효율을 방지하기 위함입니다. 지연된 할당의 진가는 응용 프로그램이 최초로 해당 가상 라인에 쓰기 연산이나 읽기 연산을 시도하는 시점에 나타납니다. MMU는 하드웨어 페이지 테이블을 탐색하다가 해당 가상의 페이지 인덱스가 가리키는 물리 체계의 엔트리가 유효하지 않음을 인지하고 CPU에 트랩(인터럽트)을 발생시킵니다. 실행 흐름이 순식간에 커널 스페이스의 페이지 폴트 핸들러인 do_page_fault() 서브루틴으로 이전됩니다. 커널은 유발 대상 주소가 VMA 리스트 내에 합법적으로 매핑되어 있는지, 접근 권한 위반(Segmentation Fault 등)은 아닌지 우선 판별합니다. 유효하지만 부재중인 공간이라면 비로소 버디 할당기(Buddy System Allocator)를 호출하여 가용한 단일 4KB 물리 프레임을 할애받습니다. 이 과정은 커널 메모리 동기화, 페이지 테이블 갱신, TLB 업데이트까지 포함되기 때문에 상당한 CPU 클럭 낭비를 강제합니다. 더욱이 이미 메모리가 고갈된 상태에서 발생한 폴트 라면 운영체제는 스왑 디먼(kswapd)을 통해 기존에 오랫동안 사용되지 않은 메모리 페이지 블록 하나를 선택해 디스크 스왑 파티션에 기록하고 프레임을 회수해야 합니다(메이저 페이지 폴트). 이러한 엄청난 디스크 I/O와 오버헤드를 막기 위해 서버 엔지니어들은 스왑 사용량을 공격적으로 억제하는 커널 패러미터를 튜닝하며, 때로는 휴즈 페이지(Huge Pages)와 같은 기술을 적용하여 페이지 변환 테이블 맵핑 자체의 계층 길이를 비약적으로 단축시키고 TLB 히트율을 기하급수적으로 이끌어 올리는 극한의 인프라스트럭처 최적화 시나리오를 집행합니다.