다른 명령
편집 요약 없음 |
편집 요약 없음 |
||
1번째 줄: | 1번째 줄: | ||
[[분류: 리눅스 커널]] | |||
== Linux struct page 개요 == | == Linux struct page 개요 == | ||
struct page는 Linux 케네어에서 물리 메모리 페이지를 관리하는 구조체이다. 각 물리 페이지마다 struct page 구조체가 존재하며, 4KB페이지마다 하나씩 존재해서, 물리 메모리에 대한 메타데이터를 저장한다. 최신 리눅스 커널에서는 Folio라는 [[Huge page]]를 위한 구조체로 한번더 감싸서, 개발자에게 Page folio에 따른 통일된 메타데이터 관리를 제공한다. | struct page는 Linux 케네어에서 물리 메모리 페이지를 관리하는 구조체이다. 각 물리 페이지마다 struct page 구조체가 존재하며, 4KB페이지마다 하나씩 존재해서, 물리 메모리에 대한 메타데이터를 저장한다. 최신 리눅스 커널에서는 Folio라는 [[Huge page]]를 위한 구조체로 한번더 감싸서, 개발자에게 Page folio에 따른 통일된 메타데이터 관리를 제공한다. |
2025년 3월 11일 (화) 03:57 기준 최신판
Linux struct page 개요
struct page는 Linux 케네어에서 물리 메모리 페이지를 관리하는 구조체이다. 각 물리 페이지마다 struct page 구조체가 존재하며, 4KB페이지마다 하나씩 존재해서, 물리 메모리에 대한 메타데이터를 저장한다. 최신 리눅스 커널에서는 Folio라는 Huge page를 위한 구조체로 한번더 감싸서, 개발자에게 Page folio에 따른 통일된 메타데이터 관리를 제공한다.
struct page의 역할
- 물리 메모리 관리: 각 페이지의 상황(Active, Swapped, Numa allocation등등)을 추적
- 각 프로세스 주소 공간과의 매핑: 각 페이지가 프로세스 각자공간과 VMA struct와 어떤 관련이 있는지, rmap을 통해서 추적
- I/O 버퍼 관리: 페이지가 파일 시스템 또는 블록 디바이스에서 사용되는 경우, Page cache관리
- Huge Page 및 NUMA 지원: Transparent Huge Page(THP), HugeTLB, NUMA 등의 메타데이터 저장
struct page 구조체
케네어 버전에 따라 struct page의 구현이 다르지만, 다음의 핵심이 되는 필드를 가지고 있음.
struct page {
unsigned long flags; /* 페이지 상태 플래그 */
union {
struct { /* Page cache and anonymous pages */
union {
struct list_head lru; /* LRU 리스트 연결 */
struct list_head buddy_list;
};
struct address_space *mapping; /* 페이지가 속한 매핑 */
union {
pgoff_t index; /* 파일에서의 페이지 오프셋 */
unsigned long share; /* FSDAX에서 공유 카운트 */
};
unsigned long private; /* 추가적인 페이지 관련 정보 */
};
struct { /* Tail pages of compound page */
unsigned long compound_head; /* Compound Page의 헤드 */
};
struct { /* ZONE_DEVICE pages */
struct dev_pagemap *pgmap;
void *zone_device_data;
};
struct rcu_head rcu_head; /* RCU 해제용 필드 */
};
union {
atomic_t _mapcount; /* Userspace 매핑된 페이지의 PTE 개수 추적 */
unsigned int page_type; /* slab이 아니고 userspace 매핑이 없을 경우 용도 추적 */
};
atomic_t _refcount; /* 페이지 참조 카운트 */
};
필드 설명
- flags: 페이지의 상태를 나타내는 플래그로, PG_locked, PG_dirty, PG_uptodate 등의 플래그가 설정된다.
- lru/buddy_list: 페이지가 LRU(Least Recently Used) 리스트에서 관리될 때 사용된다/Buddy Allocator 시스템에서 사용된다.
- mapping: 페이지가 파일 매핑이면, 해당 파일의 address_space 구조체를 가르키고, 만약 anonymous page면 reverse mapping을 가르킨다.
- index/share: I/O 버퍼 캐시 또는 파일 시스템 관련 정보 저장 용도로 된다.
- private: Buffer cache, swap buffer등 내부적인 목적으로 사용된다.
- compound_head: Transparent Huge Pages (THP) 및 HugeTLB를 지원하기 위한 필드이다. Compound Page의 경우, folio에서 첫번째 페이지를 가르킨다.
- pgmap: ZONE_DEVICE 메모리에서 사용되는 필드로, 해당 페이지가 특정 디바이스 메모리에 속해 있을 경우 pgmap과 zone_device_data를 이용해 추가 정보를 저장한다.
- rcu_head: RCU(읽기-복사 업데이트) 메커니즘을 사용할 때 사용하는 필드이다.
Reference 관련 필드
- mapcount (페이지가 매핑된 프로세스 개수)
- 이 HugePage를 매핑한 프로세스의 개수
- 각 프로세스가 mmap() 또는 fork()로 공유할 경우 증가
- Unmap 시 감소
- folio_mapcount()를 통해 확인
- _refcount (페이지 참조 횟수)
- 이 HugePage를 참조하는 총 개수
- get_page() / put_page() 호출 시 변경됨
- 보통 mapcount보다 크거나 같음 (커널 내부 참조 포함)
- entire_mapcount (전체 매핑 개수)
- 2MB HugePage를 각 PTE/PMD에 대해 참조된 개수
- mapcount는 프로세스 개수지만, entire_mapcount는 PTE 기준
- nr_pages_mapped (할당된 페이지 개수)
- 이 folio 내에서 실제로 매핑된 sub-page 수
- 일반적으로 nr_pages_mapped = folio_nr_pages(folio) * mapcount