이 코드는 어떤 문제를 푸나요?
초기화 함수는 이름을 순서대로 외우기보다 앞 함수가 뒤 함수에 무엇을 제공하는지 읽으시면 이해하기 쉽습니다. memblock은 초기 RAM 배정을 맡고, buddy는 페이지 단위 할당을 맡으며, SLUB는 작은 객체를 제공합니다. 이 함수는 그 사용 가능 시점을 순서대로 연결합니다.
읽을 범위: v6.18.37 · mm/mm_init.c · mm_core_init 2679–2729행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.
먼저 알아둘 개념
초기화 의존 관계
예를 들어 작은 객체 캐시를 만드는 데는 페이지 공급이 필요합니다. 함수 순서를 바꾸면 나중 단계가 아직 준비되지 않은 할당기를 사용할 수 있습니다.
페이지 부가 정보
struct page 외에 디버깅·추적 기능이 요구하는 추가 정보입니다. 연속 공간 요구나 할당기 준비 여부에 따라 초기화 시점이 나뉩니다.
설정에 따른 빈 함수
디버깅 기능이나 아키텍처 기능이 꺼져 있으면 해당 초기화 호출이 빈 함수로 구현될 수 있습니다. 본문에 호출이 있다고 모든 커널에서 같은 메모리를 할당하지는 않습니다.
처음 읽을 때
memblock_free_all → kmem_cache_init → vmalloc_init을 먼저 따라가세요. 각각 페이지 공급, 작은 객체, 커널 가상 주소 영역 관리가 준비되는 흐름입니다.
더 깊이 살펴볼 때
page_ext와 KHO가 어느 시점의 메모리 할당 방식에 의존하는지 확인해 보세요. 부팅 시점 메모리 회수와 런타임 할당의 경계를 찾는 연습입니다.
그림으로 보는 변화

1. 초기 할당기로 준비
연속 메타데이터와 디버깅 기반 확보
화살표는 초기화 의존 관계를 나타냅니다. 초기 단계에서는 memblock이 메모리 배정을 지원합니다.
2. 페이지와 객체 할당 준비
memblock_free_all → mem_init → kmem_cache_init
사용 가능한 페이지를 일반 할당기로 넘기고 객체 캐시를 준비하는 순서입니다.
3. 가상 주소 관리 등 확장
vmalloc_init 및 나머지 메모리 기능 초기화
페이지와 객체 공급이 준비된 뒤 그 위의 기능을 연결합니다. 실제 호출 전체는 아래 원문에 있습니다.
mm_core_init를 한 줄씩 읽기
줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.
void __init mm_core_init(void)
{
arch_mm_preinit();
hugetlb_bootmem_alloc();
/* Initializations relying on SMP setup */
BUILD_BUG_ON(MAX_ZONELISTS > 2);
build_all_zonelists(NULL);
page_alloc_init_cpuhp();
alloc_tag_sec_init();
/*
* page_ext requires contiguous pages,
* bigger than MAX_PAGE_ORDER unless SPARSEMEM.
*/
page_ext_init_flatmem();
mem_debugging_and_hardening_init();
kfence_alloc_pool_and_metadata();
report_meminit();
kmsan_init_shadow();
stack_depot_early_init();
/*
* KHO memory setup must happen while memblock is still active, but
* as close as possible to buddy initialization
*/
kho_memory_init();
memblock_free_all();
mem_init();
kmem_cache_init();
/*
* page_owner must be initialized after buddy is ready, and also after
* slab is ready so that stack_depot_init() works properly
*/
page_ext_init_flatmem_late();
kmemleak_init();
ptlock_cache_init();
pgtable_cache_init();
debug_objects_mem_init();
vmalloc_init();
/* If no deferred init page_ext now, as vmap is fully initialized */
if (!deferred_struct_pages)
page_ext_init();
/* Should be run before the first non-init thread is created */
init_espfix_bsp();
/* Should be run after espfix64 is set up. */
pti_init();
kmsan_init_runtime();
mm_cache_init();
execmem_init();
}void __init mm_core_init(void)일반 메모리 관리 기능을 부팅 중에 연결하는 함수입니다. __init으로 분류하여 초기화 코드의 수명을 표시합니다.
arch_mm_preinit();아키텍처가 공통 메모리 초기화 전에 해야 하는 준비를 수행합니다. 해당 아키텍처에 특별한 작업이 없으면 빈 구현일 수 있습니다.
hugetlb_bootmem_alloc();부팅 때 확보해야 하는 HugeTLB 큰 페이지를 준비합니다. 큰 연속 영역은 일반 할당이 진행되어 조각나기 전에 확보하는 것이 유리합니다.
BUILD_BUG_ON(MAX_ZONELISTS > 2);zonelist 개수가 코드가 예상한 범위를 벗어나면 빌드 단계에서 실패시킵니다. 실행 중 오류를 기다리는 검사가 아닙니다.
build_all_zonelists(NULL);할당 시 어느 zone을 어떤 순서로 시도할지 목록을 구성합니다. NULL은 특정 hotplug zone 하나를 추가하는 호출이 아니라 초기 전체 구성을 나타냅니다.
page_alloc_init_cpuhp();CPU가 온라인·오프라인 될 때 페이지 할당기가 처리할 콜백을 준비합니다. CPU별 페이지 캐시의 수명과 연결됩니다.
alloc_tag_sec_init();할당량을 추적하는 태그 영역을 초기화합니다. 실제 기능 포함 여부는 설정에 따라 달라집니다.
page_ext_init_flatmem();FLATMEM에서 필요한 초기 페이지 부가 정보를 준비합니다. 이후에는 얻기 어려울 수 있는 큰 연속 메모리 요구를 이 시점에 처리합니다.
mem_debugging_and_hardening_init();페이지에 검사 패턴을 채우는 poisoning, 할당·해제 때 0으로 초기화하는 보호 기능과 debug page allocation 설정을 조정합니다. 서로 함께 쓸 수 없는 요청의 우선순위를 정하고 실제 할당 경로가 사용할 static key를 켜므로 단순한 기능 이름 등록이 아닙니다.
kfence_alloc_pool_and_metadata();KFENCE가 사용할 제한된 객체 풀과 관리 정보를 확보합니다. 표본 기반 메모리 오류 검사를 위한 공간입니다.
report_meminit();스택 자동 초기화 방식과 힙 할당·해제 때 0으로 초기화하는 설정이 이번 부팅에서 켜졌는지 보고합니다. 실제 초기화 동작을 수행하는 호출과 결과를 보여 주는 호출을 구분합니다.
kmsan_init_shadow();KMSAN(Kernel Memory Sanitizer)은 값이 초기화되기 전에 사용되는 오류를 찾습니다. 이 단계는 초기 메모리의 각 값이 정의되었는지 추적할 shadow 메타데이터를 준비하며, 실제 메모리를 모두 0으로 채우는 동작과는 다릅니다.
stack_depot_early_init();여러 객체에서 같은 호출 스택이 반복될 때 스택 주소열을 공유 저장하고 작은 식별자로 참조하는 stack depot을 준비합니다. page_owner나 메모리 오류 진단이 많은 중복 스택을 따로 저장하지 않도록 합니다.
kho_memory_init();kexec handover에서 이어받을 메모리 정보를 처리합니다. memblock을 아직 사용할 수 있으면서 buddy 인계에 가까운 이 시점을 이용합니다.
memblock_free_all();예약을 제외한 사용 가능 메모리를 일반 페이지 할당기에 넘깁니다. 부팅용 구간 관리에서 페이지 할당으로 넘어가는 중요한 경계입니다.
mem_init();아키텍처별 메모리 초기화의 마무리를 수행합니다. 앞줄의 페이지 인계와 묶어서 메모리 공급이 준비되는 단계로 보시면 됩니다.
kmem_cache_init();작은 객체를 캐시별로 할당할 slab 기반을 준비합니다. 이제 페이지를 세분화해 커널 자료구조를 공급할 수 있습니다.
page_ext_init_flatmem_late();buddy와 slab 준비가 필요한 FLATMEM 부가 정보의 나머지 초기화를 수행합니다. page_owner의 스택 추적 같은 요구 때문에 앞 단계와 나뉩니다.
kmemleak_init();kmemleak은 커널의 할당 객체를 추적하고 더 이상 참조되지 않는 것으로 보이는 메모리를 누수 후보로 보고합니다. 이 호출은 초기에 기록한 할당들을 일반 추적 체계에 연결하는 초기화이며 찾은 후보를 자동으로 해제하지 않습니다.
ptlock_cache_init();페이지 테이블별 잠금을 별도 객체로 두는 구성에서 그 잠금 객체를 공급할 캐시를 만듭니다. 서로 다른 테이블을 갱신하는 CPU가 하나의 전역 잠금만으로 경쟁하지 않게 하는 기반이며 구성에 따라 빈 구현일 수 있습니다.
pgtable_cache_init();아키텍처별 페이지 테이블 객체 캐시를 준비합니다. 모든 아키텍처에서 동일한 실체를 갖는 호출은 아닙니다.
debug_objects_mem_init();초기 단계에서 추적하던 디버그 객체 정보를 일반 메모리 관리가 가능한 상태로 전환합니다.
vmalloc_init();커널의 vmalloc/vmap 가상 주소 영역 관리 기반을 초기화합니다. 물리적으로 떨어진 페이지들을 연속 가상 주소로 제공할 준비입니다.
if (!deferred_struct_pages)struct page 초기화를 뒤로 미루지 않는 구성인지 확인합니다. 남은 부가 정보를 지금 초기화할 수 있는지 결정하는 조건입니다.
page_ext_init();지연 초기화를 쓰지 않는 경우 페이지 부가 정보를 준비합니다. 앞줄 조건이 거짓이면 이 호출은 건너뜁니다.
init_espfix_bsp();필요한 아키텍처의 ESPFIX 부트 CPU 준비를 합니다. arm64 설명에서 이 호출을 arm64 고유 기능처럼 읽지 않으셔야 합니다.
pti_init();PTI(Page Table Isolation)는 사용자 실행 때 사용할 페이지 테이블에서 커널 매핑 대부분을 분리하는 완화 기법입니다. 여기서는 이를 사용하는 아키텍처의 후속 테이블 구성을 연결하며 arm64 전용 초기화로 읽으면 안 됩니다.
kmsan_init_runtime();초기화되지 않은 값의 사용을 추적하는 KMSAN의 런타임 상태를 준비합니다. 앞에서 만든 shadow 기반과 이후 실행 중 검사 코드를 연결하는 단계이며 해당 기능을 선택한 빌드에서 의미가 있습니다.
mm_cache_init();프로세스의 사용자 주소 공간을 설명할 mm_struct 객체 캐시를 만듭니다. CPU 마스크와 mm 문맥 식별 정보까지 들어갈 크기를 계산하고, 사용자와 복사할 수 있는 부분은 saved_auxv로 한정합니다. 앞에서 slab 할당기를 준비했으므로 이 캐시를 만들 수 있습니다.
execmem_init();실행 가능한 커널 메모리 할당 기반을 초기화합니다. 동적으로 생성되는 코드 등을 위한 메모리 관리로 이어집니다.
함께 생각해 볼 질문
memblock_free_all이 RAM 내용을 모두 지우나요?
아닙니다. 예약되지 않은 사용 가능 페이지를 페이지 할당기에 넘기는 과정으로 읽으셔야 합니다.
kmem_cache_init은 왜 뒤에 있나요?
객체 캐시를 운영할 페이지 공급이 먼저 필요하기 때문입니다. 실제 부트스트랩 세부 과정은 SLUB 초기화 안에서 이어집니다.
페이지 부가 정보 초기화가 여러 번 보이는 이유는 무엇인가요?
각 기능의 메모리 요구와 사용할 수 있는 할당기가 다릅니다. 초기 연속 메모리 단계와 buddy·slab 준비 이후 단계가 구분됩니다.
출처와 읽은 범위
Linux stable v6.18.37 · mm/mm_init.c
해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고
