Slub Allocator 동작 방식

ref

OverView

9706ff4d-0e3d-4b07-890f-5cddf792d773
9706ff4d-0e3d-4b07-890f-5cddf792d773

  • Page Allocator(Buddy): 페이지 할당을 요청하면 실제 물리 주소의 페이지를 할당해준다.
  • Slab Allocator: 할당받은 페이지를 slab 이라는 객체 단위로 쪼개서 사용한다. 커널은 같은 모양의 객체를 반복해서 사용하기 때문에 효율적인 메모리 관리를 위해 사용한다.
  • Slub Allocator: 슬랩할당자는 복잡한 큐 기반 캐싱 방법을 사용하는데, 최신 리눅스는 단순화하고 성능을 개선한 슬럽할당자를 사용한다.

커널영역에서 사용하는 대부분의 메모리 할당은 Slub Allocator라는 추가적인 계층 위에서 할당받은 Page 프레임을 더 쪼개서 사용한다.

Slab Allocator

커널이 할당하는 객체는 유형과 크기에 따라 캐시에 아래처럼 저장된다.
고정된 수, 고정된 크기의 객체 모임을 하나의 슬랩이라고 부른다.

ccf87a93-6cb3-4a97-8e8b-9d26e17f8045
ccf87a93-6cb3-4a97-8e8b-9d26e17f8045

각 캐시는 슬랩들을 가리키고 있는데, 전부 꽉찬 슬랩, 일부 객체만 할당된 슬랩, 완전히 빈 슬랩으로 나뉘어 연결리스트로 관리된다.
커널이 객체를 할당하려할 때 부분슬랩이나 빈 슬랩이 없는 경우에만 Page Allocator를 통해 PAGE SIZE 단위로 물리적으로 연속된 페이지를 슬랩으로 할당받게 된다.

04272b69-2271-4067-8ff2-e6635103e29d
04272b69-2271-4067-8ff2-e6635103e29d

Slub Allocator

Slab, Slub, Slob은 커널메모리를 다른 구조로 관리하게되며, 작은 임베디드는 Slob, 최신 리눅스는 Slub Allocator 를 사용하기 때문에 이 이후에는 Slub이라고 생각하면 된다.

커널은 이 슬랩할당자들을 컴파일 시점에 선택할 수 있게 제공하고 있다.
kmem_cache의 구조체부터 모양이 달라지기 때문에 mm/slab.h 에는 공통으로 사용하는 코드를 확인할 수 있고 include/linux/slab_def.h, include/linux/slub_def.h 등의 파일에서 할당자에 맞는 구조체를 볼 수 있다.

#ifdef CONFIG_SLAB
#include <linux/slab_def.h>
#endif
#ifdef CONFIG_SLUB
#include <linux/slub_def.h>
#endif

비교를 위한 Slab Allocator

위에서 Slab을 설명할 때 있던 그림이 Slab Allocator 이다.
slab.c (array_cache), slab_def.h (kmem_cache), slab.h (kmem_cache_node), struct slab

해제된 object는 CPU코어의 L1캐시에 남아있을 수 있기 때문에 재사용하면 효율이 좋다.
kmem_cache별로 크기가 일정하기 때문에 크기는 신경쓸 필요 없이 entry에서 꺼내서 할당해주면 된다.
cpu_cache에 저장된 메모리주소를 this_cpu_ptr 같은 매크로로 접근하면 CPU코어번호 기반 주소로 변경되어 접근할 수 있다.

array_cache → slabs_partial → slabs_free → new page 순으로 할당된다.

[ kmem_cache (ex. kmalloc-64) ]
   ├─ cpu_cache ──────> [ array_cache (per cpu) ]
   │                       void *entry[] # 최근 해제된 free object ptr 스택 (CPU별로 관리)
   │                       uint limit    # 캐시 최대 크기. 초과되면 batchcount 단위로 kmem_cache_node에 반납
   │
   └─ node[] ─────────> [ kmem_cache_node (per node) ]
                           ├─ slabs_partial ────┐  
                           ├─ slabs_full ───────┼──> [ struct slab ]  # from kernel 5.17
                           └─ slabs_free ───────┘      slab_cache
                                                       slab_list : kmem_cache_node 에 연결하기 위한 구조체
                                                       freelist  : 첫 freeobj 주소
                                                       active    : 사용중인 object 수
                                                       s_mem     : 첫 object 시작주소
                                                         │
                                                         v        *freelist
                                                        [obj:use][obj:free][obj:use][obj:free]
                                                                   └──── next ptr ────┘└─ next ptr ─> NULL

Slub

슬럽은 검증필요 이제 검증해야함.

[ kmem_cache ]
   ├─ cpu_slab ───────> [ kmem_cache_cpu (per cpu) ]  <-- Fast Path (Lock-free)
   │                       slab     : 현재 할당 중인 Active Slab 포인터
   │                       freelist : 다음으로 할당할 free object 주소
   │                                                                    
   └─ node[] ─────────> [ kmem_cache_node (per node) ] <-- Slow Path    
                           └─ partial ──────────┐                       
                              (Full/Free 없음)  │                      
                                                v                      
                                           [ struct slab (과거 struct page) ]
                                              slab_cache : 소속 kmem_cache
                                              freelist   : 슬랩 내 첫 free object 주소
                                              inuse      : 사용중인 object 수
                                              objects    : 슬랩 내 총 object 수
                                                │
                                                v      
                                               [obj:use][obj:free][obj:use][obj:free]
                                                          └──── next ptr ────┘└─ next ptr ─> NULL

Slub Allocator

Comments

ESC
Type to search...