첫 포스트는 커널 메모리 관리에 기반이 되는 node와 zone에 대한 내용이다.
** 커널 버전에 따라 내용이 다를 수 있고, 틀린 내용이 있을 수 있음
1. memory node
메모리 노드는 NUMA구조에서 프로세서마다 접근속도가 같은(가까운 메모리) 집합을 뱅크라고 할때, 이 뱅크를 표현하는 구조가 node이다.
NUMA(non-uniform mem access)는 멀티코어 상에서 메모리 접근의 병목현상을 해결하기 위한 방법이다.

NUMA의 자세한 구성은 다음 포스트에서 공부해보려 한다.
돌아와서 node의 사전적 정의는 위와 같지만, 풀어말하면 node란 NUMA 시스템 상에서 같은 특성을 갖는 메모리를 말한다.
같은 특성이란 프로세서 기준으로 접근속도를 얘기한다.
가까운 노드에 접근하는 속도는 빠르고, 먼 노드에 접근하는 속도는 느린데, 이게 NUMA 시스템의 특성이다.
~/include/linux/mmzone.h
node정보는 pglist_data 구조체로 관리되고, 위의 파일을 보면 매우 복잡하기도 하다.
아래는 pglist_data 구조체 코드이다.
typedef struct pglist_data {
struct zone node_zones[MAX_NR_ZONES];
struct zonelist node_zonelists[MAX_ZONELISTS];
int nr_zones;
unsigned long node_start_pfn;
unsigned long node_present_pages;
unsigned long node_spanned_pages;
int node_id;
struct task_struct *kswapd;
wait_queue_head_t kswapd_wait;
} pg_data_t;
위의 pg_data_t는 메모리 노드 하나를 통째로 관리하는 구조체이다.
흐름을 보면, 노드가 물리메모리를 zone으로 쪼개서 node_zones[]에 담아둔다. >
각 zone이 실제 페이지를 관리한다. > zone의 빈 메모리가 watermark(위험 수위) 아래로 떨어지면, 노드에 하나씩 있는 kswapd 스레드가 깨어나서 페이지를 회수한다.
2. memory zone
node자체는 접근속도에 따라 메모리 영역을 분리시킨 거고, 접근속도 외의 다른 특성에 따라 구분한 것을 zone이라고 한다.
시스템 구조는 node별로 zone들이 존재하고, zone별로 페이지가 존재한다.
결론은 zone 또한 물리메모리의 주소영역을 구분해서 관리하는 개념이다.

zone의 종류는 여러가지가 있다(DMA, DMA32, NORMAL, HIGHMEM .. )
enum zone_type {
ZONE_DMA,
ZONE_DMA32,
ZONE_NORMAL,
ZONE_HIGHMEM,
ZONE_MOVABLE,
ZONE_DEVICE,
__MAX_NR_ZONES
};
ZONE_DMA && ZONE_DMA32
DMA용 메모리 구역이다.
먼저 DMA(Direct Memory Access)는 장치가 CPU를 거치지 않고 메모리에 직접 접근하는 것이다.
(DMA는 CPU의 속도가 느려지는걸 방지하기 위해서 사용된다.)
다시 돌아와서 DMA용 메모리 구역이 따로 있는 이유는 디바이스가 바라보는 주소영역과 CPU가 바라보는 주소영역이 애초에 다르기 때문이다.
따라서 디바이스가 도달할 수 없는 주소 영역이 존재하고, 이 디바이스를 DAM시키기 위해서, 물리 메모리의 낮은 영역을 따로 DMA용 전용 구역으로 관리하는 개념이다.
DMA와 DMA32의 차이는 접근 가능한 범위가 다르다.
ZONE_DMA는 극단적으로 제약된 디바이스에게 사용되는데, 예로는 16MB이내로만 접근이 가능했던 옛날 장치들을 위한 구역이다.
ZONE_DMA32는 32비트용 디바이스를 위한 것이다. ZONE_DMA보다 넉넉하고, 4GB이내의 메모리에 접근할 수 있다.

ZONE_NORMAL
가장 일반적인 주소영역이다.
물리메모리와 가상주소가 1:1로 매핑되어있고, 유저공간과 커널공간을 나눠서 사용한다.
보통 커널 코드에서 메모리를 할당하면 접근하는 NORMAL 구역이다.

또한, 언제나 모든 시스템에서 DMA, NORMAL, HIGHMEM 세개의 zone이 존재하는것은 아니다.
64비트 시스템에서는 모든 물리메모리를 1:1매핑 가능하기 때문에 굳이 HIGHMEM을 사용하지않고 NORMAL만으로 사용가능하다.
만약에 페이지 폴트를 통해서 물리메모리가 매핑될 경우 유저공간과 커널공간 둘다 매핑된다.
ZONE_HIGHMEM
HIGHMEM은 896Mb ~ 1Gb의 영역이다.
NORMAL에서는 1Gb 보다 작은 크기를 다루기에, HIGHMEM에서는 NORMAL에서 담지 못하는 1Gb이상의 크기를 위해서 만들어 졌다.
근데 64비트 시스템에서는 모든 물리메모리를 1:1 매핑가능하므로 HIGHMEM을 굳이 사용하지 않는다.
ZONE_MOVABLE
이는 유저공간과 다르게 커널공간의 페이지들은 non-movable 페이지이기 때문에 발생하는 메모리 파편화 문제를 해결하기 위해 존재한다.
따라서 ZONE_MOVABLE 구간의 주소들은 movable하게 하여서 메모리 파편화를 방지한다.
struct_zone
struct zone {
unsigned long zone_start_pfn; /* 이 zone 시작 페이지프레임 번호(PFN) */
unsigned long present_pages; /* 이 zone에 실제 존재하는 페이지 수 */
atomic_long_t managed_pages; /* ★ 실제로 나눠줄 수 있는 페이지 수 */
struct pglist_data *zone_pgdat; /* 나를 품은 노드(pg_data_t)를 가리킴 */
const char *name; /* zone 이름 ("DMA", "Normal"...) */
struct free_area free_area[NR_PAGE_ORDERS];
/* 빈 페이지들을 크기별로 묶어둔 목록.
메모리 할당자(buddy)가 여기서 꺼내 씀 */
spinlock_t lock; /* free_area 건드릴 때 거는 락 (SMP용) */
unsigned long _watermark[NR_WMARK];
/* 빈 메모리가 이 선 아래로 떨어지면
"부족" 판단 → kswapd 깨움 */
};
Reference
https://jeongzero.oopy.io/ac68ed00-6e78-478d-9d46-0e244de12689
'Kernel > Memory Management' 카테고리의 다른 글
| Memory mapped I/O (0) | 2026.09.16 |
|---|---|
| Memory Model (0) | 2026.09.02 |