SLUB

AI
gemma-4-31b
작성자
익명
작성일
2026.08.14
조회수
None
버전
v1

SLUB (Slab Allocator)

1. 개요

SLUB리눅스 커널에서 사용하는 효율적인 커널 객체 할당자로, 메모리 단편화를 최소화하고 다중 프로세서(SMP) 환경에서 확장성을 극대화하기 위해 설계된 슬랩(Slab) 할당 방식의 구현체입니다.

리눅스 커널은 커널 내부에서 빈번하게 생성되고 파괴되는 작은 크기의 객체(예: task_struct, file 구조체 등)를 효율적으로 관리하기 위해 슬랩 할당자를 사용합니다. 과거에는 복잡한 큐 관리 방식을 사용하는 SLAB와 메모리 사용량을 극단적으로 줄인 SLOB(Simple List-Of-Blocks)가 사용되었으나, 현대의 리눅스 커널은 메타데이터 오버헤드를 줄이고 성능을 최적화한 SLUB를 기본 할당자로 채택하고 있습니다.


2. 동작 원리 및 구조

2.1 기본 개념

SLUB는 물리 메모리의 기본 단위인 페이지(Page)를 할당받아 이를 동일한 크기의 객체(Object)들로 나누어 관리합니다.

  • Slab: 하나 이상의 연속된 물리 페이지로 구성되며, 동일한 크기의 객체들의 집합입니다.
  • Object: 커널이 실제로 요청하는 메모리 단위입니다.
  • Cache: 특정 크기나 특정 구조체 전용의 슬랩 집합을 관리하는 논리적 단위입니다.

2.2 내부 데이터 구조체

SLUB는 SLAB와 달리 별도의 외부 관리 큐를 두지 않고, 페이지 구조체(struct page) 내의 필드를 활용하여 메타데이터를 저장함으로써 오버헤드를 줄입니다.

/* Simplified for conceptual understanding - Actual kernel source may vary by version */

struct kmem_cache {
    struct list_head node;          /* 노드 리스트 연결 */
    unsigned int object_size;       /* 할당할 객체의 크기 */
    
    /* CPU별 로컬 캐시 (Fast path를 위한 구조) */
    struct kmem_cache_cpu __percpu *cpu_slab; 
    
    /* 부분적으로 채워진 슬랩 리스트 (Slow path) */
    struct kmem_cache_node *node[MAX_NUMNODES];
};

struct page {
    /* SLUB에서는 page 구조체의 필드를 통해 
       다음 가용 객체의 주소를 가리키는 freelist를 관리함 */
    void *freelist; 
    unsigned int counters;
};

2.3 SLAB vs SLUB 구조적 차이

구분 SLAB (Legacy) SLUB (Modern)
메타데이터 저장 별도의 슬랩 관리 큐 및 디스크립터 사용 struct page 내부에 통합 관리
CPU 캐시 방식 복잡한 Per-CPU 큐 관리 단순화된 cpu_slab 포인터 방식
메모리 오버헤드 관리 데이터로 인한 오버헤드 높음 메타데이터 최소화로 오버헤드 낮음
확장성 (SMP) 큐 잠금(Lock) 경합 발생 가능성 높음 Lock-less 접근(Fast path) 강화로 확장성 높음
복잡도 구현 및 유지보수가 매우 복잡함 구조가 단순하며 디버깅이 용이함

3. 주요 특징 및 장점

3.1 메타데이터 오버헤드 감소

SLAB는 각 슬랩마다 관리용 큐와 상태 정보를 저장하는 별도의 메모리 영역이 필요했습니다. 반면 SLUB는 리눅스 커널의 모든 물리 페이지가 가지는 struct page 구조체의 유휴 필드를 활용하여 freelist를 관리하므로, 추가적인 메모리 낭비를 획기적으로 줄였습니다.

3.2 다중 프로세서(SMP) 확장성

SLUB는 Per-CPU Page 개념을 도입하였습니다. 각 CPU는 자신만이 사용하는 전용 슬랩을 가지며, 객체를 할당받을 때 다른 CPU와 잠금(Lock) 경합을 벌이지 않고 원자적 연산(Atomic operation)만으로 빠르게 객체를 획득할 수 있습니다.

3.3 메모리 단편화 해결 알고리즘

SLUB는 내부 및 외부 단편화를 해결하기 위해 다음과 같은 전략을 사용합니다. 1. 객체 정렬(Alignment): L1 캐시 라인에 맞춰 객체를 정렬하여 캐시 미스를 줄이고 메모리 낭비를 최적화합니다. 2. 슬랩 병합(Slab Merging): 유사한 크기와 속성을 가진 서로 다른 캐시들을 하나의 슬랩 캐시로 병합하여, 작은 크기의 파편화된 슬랩들이 여러 개 생기는 것을 방지합니다. 3. 페이지 반환: 슬랩 내의 모든 객체가 해제되어 'Empty' 상태가 되면, 해당 페이지를 즉시 버디 시스템(Buddy System)으로 반환하여 시스템 전체의 가용 메모리를 확보합니다.


4. 할당 프로세스 (Workflow)

4.1 전용 캐시와 범용 할당자

SLUB의 핵심은 특정 객체 전용 캐시를 생성하여 관리하는 것입니다. - 전용 캐시(Dedicated Cache): kmem_cache_create()를 통해 특정 구조체 전용 캐시를 생성하고, kmem_cache_alloc()을 통해 해당 크기의 객체를 할당받습니다. - 범용 할당자(<a href="/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%BB%A4%EB%84%90%20%ED%95%A8%EC%88%98/kmalloc" class="wiki-link wiki-link-missing">kmalloc</a>): kmalloc()은 내부적으로 kmalloc-32, kmalloc-64, kmalloc-128 등 크기별로 미리 생성된 전용 캐시들을 사용하는 특수한 사례입니다.

4.2 kmalloc() 호출 흐름 및 경로

사용자가 kmalloc()을 호출하면 커널은 다음과 같은 단계로 메모리를 탐색합니다.

[함수 호출 흐름] kmalloc() -> slab_alloc_node() -> __slab_alloc() -> (Fast path 또는 Slow path)

[할당 경로 다이어그램] 1. Fast Path (CPU 로컬 캐시 확인) - cpu_slab에 가용 객체가 있는가? - YES $\rightarrow$ 잠금 없이 즉시 객체 반환 $\rightarrow$ [할당 완료] - NO $\rightarrow$ Slow Path로 진입

  1. Slow Path (노드 및 시스템 메모리 확인)
  2. Step 1: Partial List 확인
    • 해당 NUMA 노드의 partial list(부분적으로 채워진 슬랩 리스트)에 가용 슬랩이 있는가?
    • YES $\rightarrow$ 슬랩을 cpu_slab으로 이동 후 객체 반환 $\rightarrow$ [할당 완료]
    • NO $\rightarrow$ Step 2로 진입
  3. Step 2: 버디 시스템(Buddy System) 할당
    • 버디 시스템에 새로운 물리 페이지 요청 $\rightarrow$ 페이지 할당 $\rightarrow$ 새로운 슬랩 생성 $\rightarrow$ 객체 반환 $\rightarrow$ [할당 완료]

4.3 빈 슬랩 관리 큐

SLUB는 슬랩의 상태를 세 가지로 분류하여 관리합니다. - Full: 모든 객체가 사용 중인 상태. - Partial: 일부 객체는 사용 중이고 일부는 비어 있는 상태. (할당 시 우선 탐색 대상) - Empty: 모든 객체가 비어 있는 상태. (메모리 압박 시 반환 대상)


5. 설정 및 디버깅

5.1 런타임 상태 확인

리눅스 커널은 /sys/kernel/slab 경로를 통해 현재 운영 중인 모든 슬랩 캐시의 상세 정보를 제공합니다.

# 전체 슬랩 정보 요약 확인
cat /proc/slabinfo

# 특정 캐시(예: kmalloc-128)의 상세 정보 확인
cat /sys/kernel/slab/kmalloc-128/detail

/proc/slabinfo 분석 예시:

Name            Active  Objs  AvgObjSize  ObjPerslab  Slab  Pages  Free
kmalloc-128      100     128   128         128         1     1      28
- Name: 캐시의 이름 - Active: 현재 사용 중인 객체 수 - Objs: 슬랩 하나당 포함된 총 객체 수 - AvgObjSize: 객체 하나의 평균 크기 (바이트) - Slab: 생성된 총 슬랩 수 - Pages: 슬랩들이 사용 중인 총 물리 페이지 수 - Free: 사용되지 않고 남아있는 객체 수

5.2 slub_debug를 이용한 탐지

커널 부팅 파라미터에 slub_debug=를 추가하여 메모리 오염(Corruption) 및 누수(Leak)를 탐지할 수 있습니다. - slub_debug=P: Poisoning (해제된 메모리에 특정 패턴을 채워 Use-after-free 탐지) - slub_debug=U: User tracking (마지막으로 객체를 할당/해제한 사용자 추적) - slub_debug=Z: Redzoning (객체 앞뒤에 가드 영역을 두어 Buffer Overflow 탐지)


6. 요약 및 한계

6.1 요약

SLUB는 현대 리눅스 커널의 하드웨어 환경(다중 코어, 대용량 메모리)에 최적화된 할당자입니다. 메타데이터를 struct page에 통합하여 메모리 효율을 높였고, Per-CPU 구조를 통해 SMP 환경에서의 잠금 경합을 제거함으로써 시스템 전반의 성능을 향상시켰습니다.

6.2 한계 및 제약 사항

  • 메모리 파편화: 슬랩 병합 알고리즘이 존재하지만, 매우 다양한 크기의 객체가 불규칙하게 할당/해제되는 환경에서는 여전히 내부 단편화가 발생할 수 있습니다.
  • 초소형 시스템 제약: 매우 적은 메모리(수 MB 단위)를 가진 임베디드 시스템에서는 SLUB의 기본 관리 구조조차 부담이 될 수 있습니다. 과거에는 이를 위해 SLOB가 사용되었으나, 리눅스 커널 6.8 버전부터 SLOB 할당자가 공식적으로 제거되었습니다. 따라서 최신 커널에서는 SLUB가 사실상 표준 할당자로 사용됩니다.
AI 생성 콘텐츠 안내

이 문서는 AI 모델(gemma-4-31b)에 의해 생성된 콘텐츠입니다.

주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.

이 AI 생성 콘텐츠가 도움이 되었나요?