커널 개발 환경 설정

Linux 커널 개발을 위한 개발 환경 구축 가이드: 필수 도구 설치, 에디터 설정, QEMU/KVM 가상 환경, 크로스 컴파일(Cross Compilation), GDB/KGDB 디버거 설정까지 완벽 정리.

전제 조건: 처음 방문했다면 메인 페이지(Page)에서 전체 학습 경로를 먼저 확인하세요. 이 문서는 바로 읽어도 되지만, 카테고리 구조를 먼저 파악하면 이후 빌드 시스템(Build System), QEMU, 디버깅(Debugging) 문서를 연결해서 따라가기 쉽습니다.
일상 비유: 이 주제는 작업장 공구 세팅과 비슷합니다. 목공 작업에 톱, 망치, 드릴이 필요하듯이, 커널 개발에는 컴파일러, 디버거, 에디터가 필수입니다. 도구를 제대로 갖추면 작업 효율이 크게 높아집니다.

핵심 요약

  • 필수 도구 — gcc, make, git, flex, bison, libelf-dev 등 빌드에 필수적인 패키지를 먼저 설치합니다.
  • 개발 보조 도구 — ctags, cscope, clangd 등으로 코드 탐색과 자동완성을 강화합니다.
  • 가상 환경 — QEMU/KVM으로 안전하게 커널을 테스트하고 디버깅(Debugging)합니다.
  • 크로스 컴파일 — ARM, ARM64, RISC-V 등 다른 아키텍처용 커널을 빌드합니다.
  • 디버거 설정 — GDB/KGDB로 커널 소스 레벨 디버깅을 수행합니다.

단계별 이해

  1. 도구 설치
    배포판에 맞는 패키지 관리자로 필수 도구를 설치합니다.

    왜? 커널 빌드는 GCC/Clang 컴파일러 외에도 flex·bison(파서 생성), libelf-dev(BPF 지원), bc(설정 스크립트 계산) 등 수십 개의 보조 도구가 얽혀 있습니다. 하나라도 빠지면 make defconfig 단계에서 즉시 오류가 나므로, 첫 단계에서 올바른 패키지 세트를 설치해야 이후 과정이 막히지 않습니다.

  2. 에디터 구성
    선호하는 에디터에 코드 탐색 도구를 연동합니다.

    왜? 커널 소스는 약 4,000만 줄에 달합니다. ctags·cscope·clangd 없이 grep만으로 함수 정의와 호출 관계를 추적하면 수십 분이 걸립니다. compile_commands.json을 생성하면 에디터가 커널 매크로와 조건부 컴파일 분기까지 이해해 정확한 자동완성·점프가 가능해집니다.

  3. 가상 환경 준비
    QEMU/KVM으로 테스트용 가상 머신을 구성합니다.

    왜? 실제 하드웨어에서 커널 버그를 실험하면 시스템이 패닉(Panic)에 빠지거나 파일시스템이 손상될 수 있습니다. QEMU는 빌드한 커널 이미지를 격리된 환경에서 1초 안에 부팅하고, 크래시(Crash)가 발생해도 호스트에 영향을 주지 않습니다. GDB 원격 디버깅 포트도 QEMU 옵션 한 줄로 열립니다.

  4. 첫 빌드 실행
    간단한 설정으로 커널을 빌드하고 부팅 테스트합니다.

    왜? make defconfig는 현재 아키텍처의 합리적 기본값을 적용한 최소 빌드 설정입니다. 30,000개 이상의 옵션을 직접 건드리기 전에 이 설정으로 먼저 전체 빌드~QEMU 부팅 루프가 동작하는지 확인해야, 이후 옵션 추가 시 문제의 원인이 새 설정에 있다고 특정할 수 있습니다.

  5. 디버거 연동
    GDB와 QEMU를 연결하여 커널 디버깅 환경을 완성합니다.

    왜? 커널에서 printk만으로 디버깅하면 심각한 타이밍 의존 버그나 메모리 오염은 발견하기 어렵습니다. CONFIG_DEBUG_INFO로 빌드한 커널과 QEMU의 -s -S 옵션을 함께 사용하면, GDB에서 커널 소스 라인 단위 중단점·변수 조사·스택 트레이스를 실시간(Real-time)으로 수행할 수 있습니다.

환경 설계 원칙

커널 개발 환경은 단순 설치보다 재현성, 격리(Isolation), 검증 가능성이 중요합니다. 처음 한 번만 잘 구성하면 이후 실험 속도와 안정성이 크게 올라갑니다.

원칙 설명 실무 권장
재현성 같은 입력이면 같은 빌드 결과가 나와야 함 툴 버전 고정, 설정 파일(.config) 보관, 빌드 로그 아카이브
격리 호스트 시스템과 테스트 환경 분리 QEMU/KVM 기본, 실제 장비는 후반 검증 단계에서만 사용
검증 가능성 문제 발생 시 원인 추적이 가능해야 함 CONFIG_DEBUG_INFO, FRAME_POINTER, 로그 수집 자동화
점진적 확장 필수 도구부터 시작해 점진적으로 추가 필수(빌드) → 권장(탐색/가상화(Virtualization)) → 선택(분석/자동화)
권장 시작 프로필: 초반에는 단일 아키텍처(x86_64) + QEMU + GDB 조합으로 시작하세요. 크로스 컴파일과 고급 분석 도구는 기본 루프(수정→빌드→부팅→디버깅)가 안정화된 뒤 추가하는 편이 전체 학습 속도가 빠릅니다.

개발 도구 의존성 로드맵

커널 개발 환경은 여러 도구들이 계층적으로 연결된 생태계입니다. 아래 다이어그램은 각 도구의 역할과 의존 관계를 보여주며, 환경 구축 순서를 안내합니다.

커널 개발 도구 의존성 로드맵 - 계층별 설치 순서 L0 기본 시스템 기반 Linux 배포판 패키지 관리자 Bash · Shell Python 3 Perl L1 핵심 빌드 도구 필수 GCC gcc 12+ GNU Make make 3.82+ binutils ld · as · ar flex · bison 파서 생성기 libelf-dev BTF · BPF libssl-dev 모듈 서명 Git 버전 관리 2A 코드 탐색 권장 ctags 심볼 인덱싱 cscope 참조 추적 clangd LSP 서버 ripgrep 빠른 검색 2B 가상화 권장 QEMU 머신 에뮬레이터 KVM 하드웨어 가속 virtme-ng 빠른 테스트 busybox 최소 사용자 공간 L3 디버깅 · 분석 선택 GDB 소스 레벨 디버깅 crash vmcore 분석 perf 성능 프로파일링 trace-cmd ftrace 프론트엔드 bpftrace 동적 추적 sparse 정적 분석 coccinelle 코드 변환 checkpatch 코딩 스타일 검사 pahole 구조체 메모리 분석 L4 고급 도구 전문가 크로스 컴파일 툴체인 ccache · distcc clang · LLVM ktest · kernelci syzkaller (fuzzing) b4 (패치(Patch) 관리) Rust 툴체인
그림: 커널 개발 도구 의존성 로드맵 — 계층별 설치 순서
💡

환경 구축 권장 순서:

  1. 최소 환경 (1~2시간): Layer 0-1 + QEMU → 간단한 커널 빌드/부팅 가능
  2. 기본 개발 (반나절): + Layer 2A/2B → 코드 탐색 및 가상머신 테스트
  3. 완전한 환경 (1일): + Layer 3 → 디버깅 및 분석까지 모든 작업 가능
  4. 전문가 환경 (지속): + Layer 4 → 다중 아키텍처 개발 및 자동화

디스크 공간: 커널 소스 3GB + 빌드 결과 10GB + 가상머신 이미지 5GB = 최소 20GB 여유 필요

커널 빌드 파이프라인(Build Pipeline) 개요

make -j$(nproc) 한 줄 뒤에서는 수만 개의 C 소스 파일이 6단계 변환 과정을 거쳐 최종 vmlinux와 bzImage로 합쳐집니다. 이 흐름을 이해하면 "왜 이 도구가 필요한가?"가 자연스럽게 풀립니다.

커널 빌드 파이프라인 6단계 — make 명령이 조율하는 소스에서 vmlinux/bzImage 까지의 변환 흐름 $ make -j$(nproc) 소스 코드 .c · .h · .S · 수만 개 1 전처리 cpp (gcc -E) #include·#define 매크로를 모두 전개 2 컴파일 gcc cc1 · clang 최적화 후 C 코드를 어셈블리 코드로 변환 3 어셈블 GNU as · llvm-as 어셈블리를 기계어 오브젝트로 변환 4 링크 ld · lld 모든 .o 와 lib 를 하나의 ELF 로 결합 5 BTF 생성 pahole DWARF → BTF 변환 BPF·eBPF 타입 지원 6 패키징 objcopy · scripts/ 압축하고 부트 코드와 결합해 부팅 이미지 생성 .i .s .o vmlinux arch/x86/boot/bzImage 부팅 가능한 커널 이미지 Kbuild 시스템이 전체 흐름을 조율 — Makefile 계층 구조와 .config 설정을 읽어 대상·도구·옵션을 결정 ※ 실제로는 gcc 한 번의 호출이 ①전처리 → ②컴파일 → ③어셈블을 연속 수행하며, -j$(nproc) 옵션은 서로 다른 파일들을 병렬 처리합니다
그림: 커널 빌드 파이프라인 — make 한 줄이 내부적으로 실행하는 6단계 변환
단계담당 도구입력출력패키지
① 전처리 cpp (gcc 내장) .c, .h 매크로(Macro) 전개된 C 텍스트 gcc
② 컴파일 gcc cc1 / clang 전처리 결과 어셈블리(Assembly) 코드 (.s) gcc / clang
③ 어셈블 as (GNU binutils) .s / .S 오브젝트 파일(.o) binutils
④ 링크 ld (GNU binutils) 수천 개의 .o vmlinux (ELF) binutils
⑤ BTF 생성 pahole vmlinux DWARF 정보 BTF 섹션 삽입 (BPF·eBPF 지원) dwarves
⑥ 패키징 objcopy, 커널 스크립트 vmlinux bzImage / Image.gz binutils, bc
Kbuild 시스템이란? 커널 전용 빌드 시스템으로, 루트 Makefile이 각 서브시스템 Makefile을 재귀 호출하여 병렬 컴파일을 조율합니다. obj-y(빌트인), obj-m(모듈), obj-$(CONFIG_XXX)(조건부)로 빌드 대상을 선언하며, Kconfig 설정에 따라 어떤 파일을 컴파일할지 결정합니다. 개발 중에는 make drivers/net/my_driver.o처럼 단일 파일만 재컴파일하는 것도 가능합니다.

GCC 버전 요구사항

리눅스 커널은 아키텍처별로 최소 GCC 버전이 다릅니다. Linux 6.16 (2025 년 7 월) 부터는 모든 아키텍처에서 GCC 8 이상이 필수입니다. x86_64 는 이미 이전부터 GCC 8 을 요구했으며, 6.16 에서 다른 아키텍처도 통일되었습니다.

# GCC 버전 확인
gcc --version

# 커널 소스에서 요구하는 최소 버전 확인
cat scripts/min-tool-version.sh | grep -A5 "gcc"
주의: GCC 7 이하는 Linux 6.16+ 빌드가 불가능합니다. Ubuntu 18.04 등 오래된 배포판은 GCC 9+ 로 업그레이드하거나, Ubuntu 22.04+/Debian 12+ 같은 최신 배포판을 사용하세요.

필수 개발 도구 설치

Linux 커널 빌드를 위해서는 컴파일러, 빌드 시스템, 버전 관리 시스템, 그리고 다양한 유틸리티가 필요합니다. 배포판별로 패키지 이름이 다를 수 있으므로 각 배포판에 맞는 명령어를 사용하세요.

Ubuntu / Debian 계열

# [필수] 컴파일러 / 빌드 도구
sudo apt update
sudo apt install -y build-essential \
  gcc make git pkg-config \
  flex bison

# [필수] 커널 빌드 의존 라이브러리
sudo apt install -y libelf-dev libssl-dev \
  bc libncurses-dev

# [필수] 초기 램디스크 및 모듈 도구
sudo apt install -y cpio rsync kmod

# [선택] 정적 분석 / 빌드 최적화 / BTF
sudo apt install -y dwarves sparse ccache

# [선택] 커널 문서 빌드 도구
sudo apt install -y python3-sphinx \
  texlive-latex-base texlive-latex-extra
패키지 설명:
  • build-essential: gcc, g++, make 등 기본 빌드 도구 모음
  • flex, bison: 파서 생성기 (커널 빌드 스크립트에서 사용)
  • libelf-dev: BPF, eBPF 프로그램 빌드에 필요
  • libssl-dev: 서명된 커널 모듈 빌드에 필요
  • bc: 커널 빌드 스크립트의 계산기
  • libncurses-dev: menuconfig TUI에 필요
  • pkg-config: libelf, openssl 등 라이브러리 존재 여부를 스크립트로 검증할 때 사용
  • dwarves: pahole 등 DWARF 디버깅 정보 분석 도구
  • sparse: 정적 분석 도구
  • ccache: 컴파일러 캐시(Cache)로 재빌드 속도 향상
비직관적 의존성 — 왜 이 패키지가 필요한가?
패키지빌드 파이프라인 역할없으면?
flex / bison Kconfig 파서와 일부 커널 서브시스템(DTB 컴파일러 등)의 렉서·파서를 소스에서 생성합니다. 커널 scripts/kconfig/ 디렉토리가 이를 사용합니다. make defconfig 또는 menuconfig 단계에서 "No rule to make target" 오류
libelf-dev ELF(Executable and Linkable Format) 파일 파싱 라이브러리. pahole(BTF 생성), BPF 로더(Loader), objtool이 의존합니다. CONFIG_DEBUG_INFO_BTF 또는 BPF 관련 빌드에서 링크 오류
bc 셸에서 부동소수점 없이 정밀 정수 연산이 필요한 커널 빌드 스크립트(예: 아키텍처별 타임슬롯 계산)에 사용됩니다. arch 별 빌드 스크립트 중간에 "bc: command not found" 오류
dwarves (pahole) vmlinux에 포함된 DWARF 타입 정보를 읽어 BTF(BPF Type Format) 섹션을 삽입합니다. BPF 프로그램이 커널 구조체 오프셋(Offset)에 접근하는 데 필수입니다. CONFIG_DEBUG_INFO_BTF=y 빌드 시 "FAILED: load BTF from vmlinux" 오류
libssl-dev 커널 모듈 서명(CONFIG_MODULE_SIG) 및 보안 부트(Secure Boot) 지원에 사용됩니다. scripts/sign-file.c가 OpenSSL API를 호출합니다. 모듈 서명 빌드 시 헤더 누락 컴파일 오류
libncurses-dev make menuconfig의 TUI(Terminal UI)를 렌더링하는 ncurses 라이브러리입니다. make menuconfig 실행 시 "Your display is too small" 또는 링크 오류

설치 직후 검증 명령

패키지 설치가 끝나면 바로 아래 명령으로 도구 상태를 확인하세요. 설치 자체보다 실행 가능한 상태를 검증하는 과정이 중요합니다.

# 필수 도구 버전 확인
gcc --version | head -1
make --version | head -1
git --version
ld --version | head -1
flex --version
bison --version | head -1

# 커널 빌드 관련 라이브러리 존재 확인
pkg-config --modversion libelf
openssl version

# 커널 소스에서 최소 빌드 검증
make mrproper
make defconfig
make -j$(nproc) bzImage
검증 포인트: make defconfig가 실패하면 ncurses, flex, bison, bc 계열 의존성이 누락됐을 가능성이 큽니다. bzImage 빌드가 실패하면 컴파일러/링커(Linker)/헤더 버전 조합을 우선 확인하세요.

버전 관리 정책

커널 개발에서는 "최신 버전"보다 "팀 전체에서 동일한 조합"이 더 중요할 때가 많습니다. 도구 버전을 팀 기준으로 고정하면 재현 불가 버그를 크게 줄일 수 있습니다.

도구 최소 버전 요구사항 (v6.14+ / v7.2+ 기준)

아래는 커널 Documentation/process/changes.rst에 명시된 공식 최소 버전과 실무 권장 버전입니다. 최소 버전 미만의 도구로 빌드하면 경고 또는 오류가 발생합니다. 커널 버전마다 최소 버전이 상이할 수 있으므로, 실제 빌드하려는 커널 소스 트리에서 scripts/min-tool-version.sh를 실행하여 정확한 최소 버전을 확인하세요.

도구 최소 버전 (v6.14) 최소 버전 (v7.2+ / 현재) 권장 버전 비고
GCC 5.1 (parisc64: 12.0) 8.1 (parisc64: 12.0) 13+ v6.13까지 5.1, v6.16부터 8.1 이상. 실무에서는 12+ 권장
Clang/LLVM 13.0.1 (s390: 15.0, loongarch: 18.0) 17.0.1 (loongarch: 18.0, s390: 17.0.1) 19+ v6.14: 13.0.1, v7.2+: 17.0.1. AutoFDO는 LLVM 17+ 필요
Rust (선택) 1.78.0 1.85.0 (s390: 1.96.0) 최신 stable CONFIG_RUST 활성화 시 필요. v7.1부터 1.85.0(s390 1.96.0)
bindgen (선택) 0.65.1 0.71.1 최신 Rust C 바인딩(Binding) 생성기. v7.1부터 0.71.1
GNU Make 4.0 4.0 4.4+ v6.14+에서 4.0 이상 필수
binutils 2.25 2.30 2.40+ ld, as, ar, objcopy 포함. v6.14: 2.25, v7.0+: 2.30
flex 2.5.35 2.5.35 2.6+
bison 2.0 2.0 3.8+
pahole 1.16 1.26 1.26+ BTF 생성 (CONFIG_DEBUG_INFO_BTF). v6.14: 1.16, v7.2+ 전면 1.26 (v7.0부터는 KF_IMPLICIT_ARGS kfunc 사용 시 1.26 필수)
Perl 5 5 5.34+ checkpatch.pl, 빌드 스크립트
Python 3.5.x (선택) 3.9.x 3.10+ Sphinx 문서, 빌드/테스트 스크립트. v6.14는 선택(3.5.x), 현재(v7.2+)는 필수(3.9.x)
Sphinx 2.4.4 3.4.3 최신 커널 문서 빌드용
openssl 1.0.0 1.0.0 3.x 모듈 서명 (CONFIG_MODULE_SIG)
버전 확인 방법: scripts/min-tool-version.sh로 현재 커널 소스가 요구하는 도구 최소 버전을 즉시 확인할 수 있습니다. 이 스크립트는 커널 소스 트리마다 해당하는 최소 버전을 반환하므로, 빌드하려는 커널 버전의 소스 디렉토리에서 실행하세요.
# 커널 소스 디렉토리에서 실행 (현재 트리의 최소 버전 반환)
scripts/min-tool-version.sh gcc       # 예: 5.1 (v6.14), 8.1 (v7.2+)
scripts/min-tool-version.sh llvm      # 예: 13.0.1 (v6.14), 17.0.1 (v7.2+)
scripts/min-tool-version.sh rustc     # 예: 1.78.0 (v6.11~v7.0), 1.85.0 (v7.1+)
scripts/min-tool-version.sh bindgen   # 예: 0.65.1 (v6.11~v7.0), 0.71.1 (v7.1+)
scripts/min-tool-version.sh binutils  # 예: 2.25 (v6.14), 2.30 (v7.2+)
Rust/bindgen 버전 정책(Rust-for-Linux): Rust-for-Linux는 현재 Debian stable(2025.08 릴리스된 Trixie 기준)에 탑재된 Rust/bindgen 버전을 기준선으로 추적합니다. 이에 따라 v7.1부터 최소 요구값이 rustc 1.85.0·bindgen 0.71.1로 상향되었습니다(v6.11~v7.0까지는 rustc 1.78.0·bindgen 0.65.1, s390은 rustc 1.96.0). 실제 요구값은 커널 트리의 scripts/min-tool-version.sh와 Rust-for-Linux 정책 문서를 우선 확인해야 합니다. 빌드 환경을 미리 맞추려면 rustup으로 최신 stable을 설치하고 rust-src 컴포넌트와 bindgen-cli를 최신 버전으로 유지하는 것을 권장합니다.

Fedora / RHEL / CentOS 계열

# [필수] 컴파일러 / 빌드 도구
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y gcc make git pkgconf-pkg-config \
  flex bison

# [필수] 커널 빌드 의존 라이브러리
sudo dnf install -y elfutils-libelf-devel openssl-devel \
  bc ncurses-devel

# [필수] 초기 램디스크 및 모듈 도구
sudo dnf install -y cpio rsync kmod

# [선택] 정적 분석 / 빌드 최적화 / BTF
sudo dnf install -y dwarves sparse ccache

Arch Linux

# [필수] 컴파일러 / 빌드 도구
sudo pacman -S --needed base-devel pkgconf \
  gcc make git \
  flex bison

# [필수] 커널 빌드 의존 라이브러리
sudo pacman -S --needed libelf openssl \
  bc ncurses

# [필수] 초기 램디스크 및 모듈 도구
sudo pacman -S --needed cpio rsync kmod

# [선택] 정적 분석 / 빌드 최적화 / BTF
sudo pacman -S --needed pahole sparse ccache

openSUSE / SLES 계열

openSUSE와 SLES(SUSE Linux Enterprise Server)는 zypper 패키지 관리자를 사용합니다. openSUSE는 커널 개발과 관련해 SUSE 커널 팀과도 밀접한 배포판으로, 커널 빌드 지원이 활발합니다.

# [필수] 컴파일러 / 빌드 도구
sudo zypper install -y gcc make git pkgconf \
  flex bison

# [필수] 커널 빌드 의존 라이브러리
sudo zypper install -y libelf-devel \
  libopenssl-devel bc ncurses-devel

# [필수] 초기 램디스크 및 모듈 도구
sudo zypper install -y cpio rsync kmod

# [선택] 정적 분석 / 빌드 최적화 / BTF
sudo zypper install -y dwarves sparse ccache
패키지 참고: openSUSE에서 pkg-config 명령은 pkgconf 패키지가 제공합니다. OpenSSL 개발 헤더는 libopenssl-devel(또는 버전별 libopenssl-3-devel) 패키지에 포함되어 있습니다.

Gentoo

Gentoo는 Portage 패키지 관리자를 사용합니다. 소스 기반 배포판이므로 커널 개발에 필요한 패키지 설치와 컴파일 플래그 제어가 자유로우며, 커널과 도구를 소스에서 직접 빌드하는 환경에 적합합니다. emerge는 기본적으로 root 권한으로 실행합니다.

# [필수] 컴파일러 / 빌드 도구
emerge --ask --verbose sys-devel/gcc dev-build/make \
  sys-devel/flex sys-devel/bison dev-vcs/git \
  dev-util/pkgconf

# [필수] 커널 빌드 의존 라이브러리
emerge --ask --verbose dev-libs/libelf \
  dev-libs/openssl sys-libs/ncurses

# [필수] 초기 램디스크 및 모듈 도구
emerge --ask --verbose app-arch/cpio \
  net-misc/rsync sys-apps/kmod

# [선택] 정적 분석 / 빌드 최적화 / BTF
emerge --ask --verbose sys-devel/sparse \
  dev-util/ccache dev-util/pahole
USE 플래그: Gentoo에서는 전역 USE 플래그가 없으면 일부 라이브러리가 선택적으로 비활성화될 수 있습니다. 예를 들어 BTF 생성을 위해 pahole(dwarves)이 정상 동작하려면 /etc/portage/package.use에 필요한 USE 플래그를 활성화해야 합니다.

Alpine Linux

Alpine Linux는 musl libc와 BusyBox 기반의 경량 배포판입니다. apk 패키지 관리자를 사용하며, 기본 사용자가 root인 경우가 많아 sudo 없이 실행할 수 있습니다. 컨테이너나 임베디드 환경에서 커널을 가볍게 빌드할 때 유용합니다.

# [필수] 컴파일러 / 빌드 도구
apk add build-base gcc make git pkgconf \
  flex bison

# [필수] 커널 빌드 의존 라이브러리
apk add elfutils-dev openssl-dev \
  bc ncurses-dev

# [필수] 초기 램디스크 및 모듈 도구
apk add cpio rsync kmod

# [선택] 정적 분석 / 빌드 최적화 / BTF
apk add sparse ccache dwarves
musl 주의: Alpine은 glibc 대신 musl libc를 사용합니다. 대부분의 커널 빌드 도구는 musl에서도 동작하지만, 일부 배포판 전용 바이너리 패키지나 gdb-multiarch 같은 도구의 의존성이 glibc 전용일 수 있습니다. 또한 Alpine 기본 GCC는 오래된 버전일 수 있으므로 커널 최소 버전 요구사항(scripts/min-tool-version.sh)을 반드시 확인하세요.

Void Linux

Void Linux는 독립적으로 개발되는 배포판으로 xbps 패키지 관리자를 사용합니다. glibc와 musl 두 가지 변형이 존재하며, 아래는 glibc 기준 명령입니다.

# [필수] 컴파일러 / 빌드 도구
sudo xbps-install -S base-devel gcc make git \
  pkg-config flex bison

# [필수] 커널 빌드 의존 라이브러리
sudo xbps-install -S elfutils-devel \
  openssl-devel bc ncurses-devel

# [필수] 초기 램디스크 및 모듈 도구
sudo xbps-install -S cpio rsync kmod

# [선택] 정적 분석 / 빌드 최적화 / BTF
sudo xbps-install -S pahole sparse ccache
패키지 참고: Void에서 ELF/libelf 개발 헤더는 elfutils-devel 패키지가 제공하며, BTF/pahole 도구는 pahole 패키지에 포함되어 있습니다. clang/lld는 llvm 소스 패키지가 생성하는 하위 패키지로, xbps-install clang lld로 설치할 수 있습니다.

LLVM/Clang 대체 툴체인

리눅스 커널은 GCC 외에도 LLVM/Clang으로 공식 빌드를 지원합니다. Clang은 더 상세한 경고 메시지, CFI(Control Flow Integrity), 링크 타임 최적화(LTO) 등 GCC에 없는 보안/최적화 기능을 제공합니다.

LLVM/Clang 설치

# Ubuntu/Debian (배포판 기본 LLVM 패키지)
sudo apt install -y clang lld llvm

# Fedora
sudo dnf install -y clang lld llvm

# Arch Linux
sudo pacman -S clang lld llvm

# Gentoo (LLVM 프로파일을 활성화한 경우)
emerge --ask --verbose llvm-core/clang llvm-core/lld \
  llvm-core/llvm

# openSUSE
sudo zypper install -y clang lld llvm

# Alpine Linux
apk add clang lld llvm

# Void Linux
sudo xbps-install -S clang lld llvm
버전 선택 기준: 업스트림 커널 문서는 배포판이 제공하는 최신 stable LLVM 사용을 일반적으로 권장합니다. 배포판 기본 패키지가 너무 오래됐다면 별도 LLVM 저장소나 kernel.org에서 제공하는 사전 빌드 LLVM을 검토하세요.

Clang으로 커널 빌드

# 기본 Clang 빌드
make CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm \
     STRIP=llvm-strip OBJCOPY=llvm-objcopy \
     OBJDUMP=llvm-objdump READELF=llvm-readelf \
     HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar \
     defconfig

# 간편한 방법: LLVM=1 (모든 도구를 LLVM으로)
make LLVM=1 defconfig
make LLVM=1 -j$(nproc)

# 접미사 버전 패키지(clang-18 등)를 설치했다면
make LLVM=-${LLVM_VERSION} defconfig
make LLVM=-${LLVM_VERSION} -j$(nproc)

# Clang으로 크로스 컴파일 (단일 바이너리로 모든 아키텍처)
make LLVM=1 ARCH=arm64 defconfig
make LLVM=1 ARCH=arm64 -j$(nproc)

# AutoFDO 빌드 (v6.13+, LLVM 17+ 필요)
# 1단계: 프로파일 수집용 커널 빌드
make LLVM=1 defconfig
./scripts/config --enable AUTOFDO_CLANG
make LLVM=1 -j$(nproc)
# 2단계: perf로 프로파일 수집 후 재빌드
# perf record -b -o perf.data -- workload
# create_llvm_prof --binary=vmlinux --out=afdo.prof
# make LLVM=1 CLANG_AUTOFDO_PROFILE=afdo.prof -j$(nproc)

Clang 전용 기능

기능 설정 옵션 설명
CFI CONFIG_CFI_CLANG 간접 호출 대상 검증, 코드 재사용 공격 방어
LTO (Thin) CONFIG_LTO_CLANG_THIN 링크 타임 최적화 (전체 프로그램 최적화)
Shadow Call Stack CONFIG_SHADOW_CALL_STACK ROP 공격 방어 (ARM64)
KCFI CONFIG_CFI_CLANG 커널 전용 CFI 구현 (v6.1+, 기존 CFI 대체)
Auto-init CONFIG_INIT_STACK_ALL_ZERO 스택 변수 자동 초기화 (정보 유출 방지)
AutoFDO CONFIG_AUTOFDO_CLANG 프로파일 기반 최적화, perf 데이터로 핫 패스 최적화 (v6.13+, LLVM 17+)
Propeller CONFIG_PROPELLER_CLANG 포스트 링크 코드 레이아웃 최적화, AutoFDO와 병용 (v6.13+, LLVM 17+)

GCC vs Clang 비교

항목 GCC Clang/LLVM
역사 커널 공식 기본 컴파일러 4.x부터 공식 지원, Android 커널 기본
에러 메시지 간결 상세하고 컬러풀, 제안 포함
경고 수준 보수적 더 많은 잠재 문제 감지
크로스 컴파일 아키텍처별 별도 툴체인 단일 바이너리로 모든 아키텍처
LTO 지원 (느림) ThinLTO로 빠르고 효율적
보안 기능 기본 CFI, Shadow Call Stack 등 추가
빌드 속도 보통 비슷하거나 약간 빠름
플러그인 GCC 플러그인 지원 미지원 (대안 기능 제공)
실무 권장: 개발 중에는 GCC와 Clang 모두로 빌드하면 더 많은 경고를 잡을 수 있습니다. GCC에서 통과하는 코드가 Clang에서 경고를 발생시키는 경우(또는 그 반대)가 적지 않습니다. CI에서 양쪽 컴파일러 모두 테스트하는 것이 이상적입니다.
# 양쪽 컴파일러로 빌드 테스트
# GCC 빌드
make O=build-gcc defconfig
make O=build-gcc -j$(nproc) 2>&1 | tee gcc-warnings.log

# Clang 빌드
make O=build-clang LLVM=1 defconfig
make O=build-clang LLVM=1 -j$(nproc) 2>&1 | tee clang-warnings.log

# 경고 비교
diff <(grep "warning:" gcc-warnings.log | sort) \
     <(grep "warning:" clang-warnings.log | sort)

Rust 커널 개발 환경

리눅스 커널은 v6.1부터 Rust를 지원하기 시작했으며, Linux 7.0 (2026년 4월 12일)에서 experimental 태그가 제거되어 stable로 전환되었습니다. v6.12~v7.0에 걸쳐 Rust 추상화 계층이 크게 확장되어, 디바이스 드라이버(Device Driver)와 파일시스템(Filesystem) 모듈을 Rust로 작성할 수 있는 기반이 마련되었습니다. Rust는 이제 C와 나란히 공식 커널 지원 언어로, 새로운 커널 코드 작성에 있어 memory safety를 보장하는 선택지가 되었습니다.

Rust 툴체인 설치

# rustup으로 Rust 설치 (커널이 요구하는 특정 버전)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

# 커널 소스에서 요구하는 Rust 버전 확인
cd /path/to/linux
scripts/min-tool-version.sh rustc    # 예: 1.85.0 (v7.1+), 1.78.0 (v6.11~v7.0)
scripts/min-tool-version.sh bindgen  # 예: 0.71.1 (v7.1+), 0.65.1 (v6.11~v7.0)

# 해당 버전 설치 및 필수 컴포넌트 추가
rustup override set $(scripts/min-tool-version.sh rustc)
rustup component add rust-src

# bindgen 설치
cargo install --locked bindgen-cli

# Rust 지원 여부 확인
make LLVM=1 rustavailable
요구사항: Rust 커널 빌드는 LLVM=1(Clang)을 필수로 사용합니다. GCC만으로는 Rust 커널 코드를 빌드할 수 없습니다. make rustavailable이 성공하면 CONFIG_RUST=y를 활성화할 수 있습니다.

Rust 포함 커널 빌드

# Rust 활성화 커널 빌드
make LLVM=1 defconfig
./scripts/config --enable RUST
make LLVM=1 -j$(nproc)

# Rust 샘플 모듈 활성화 (학습용)
./scripts/config --enable SAMPLE_RUST_MINIMAL
./scripts/config --enable SAMPLE_RUST_PRINT
make LLVM=1 -j$(nproc)

Rust 커널 프로그래밍의 상세 가이드 — 추상화 계층, 드라이버 작성, 안전성 모델, KUnit 연동은 별도 페이지로 분리되었습니다.

Rust 커널 프로그래밍 가이드 → | Rust 언어 기초~고급 →

코드 탐색 도구

대규모 C/C++/Rust 코드베이스에서 함수 정의·참조·호출 그래프를 빠르게 탐색하려면 언어 서버(LSP) 기반 도구와 전통적 태그 도구를 조합하는 것이 표준입니다. 커널 특유의 매크로, 조건부 컴파일, 생성 코드(Kconfig)를 올바르게 처리하려면 compile_commands.json 생성이 필수입니다.

compile_commands.json 생성

# 방법 1: 커널 내장 스크립트 (권장)
./scripts/clang-tools/gen_compile_commands.py

# 방법 2: Bear로 인터셉트 (빌드 시스템 독립적)
sudo apt install bear
bear -- make -j$(nproc) bzImage

# 방법 3: CMake 기반 프로젝트용 (커널은 위 방법 사용)
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
팁: compile_commands.json은 커널 루트에 생성됩니다. 심볼릭 링크로 프로젝트 루트에도 두면 에디터가 자동 인식합니다:
ln -sf /path/to/linux/compile_commands.json /path/to/project/compile_commands.json

clangd: LSP 기반 C/C++ 탐색

clangd는 LLVM 기반 언어 서버로, compile_commands.json을 읽어 매크로 전개, 템플릿 인스턴스화, 조건부 컴파일 분기까지 정확하게 해석합니다.

# 설치
sudo apt install clangd  # Ubuntu/Debian
sudo dnf install clang-tools-extra  # Fedora
pacman -S clang  # Arch (clangd 포함)

# 버전 확인 (최신 stable 권장, 17+ 이상)
clangd --version

.clangd 설정 파일 (프로젝트 루트 또는 ~/.config/clangd/config.yaml):

# .clangd
CompileFlags:
  Add: ["-D__KERNEL__", "-DCONFIG_AS_CFI=1", "-DCONFIG_AS_CFI_SIGNAL_FRAME=1"]
  Remove: ["-mno-sse", "-mno-mmx", "-mno-sse2", "-mno-3dnow"]
Index:
  Background: Build
  StandardLibrary: Yes
Diagnostics:
  UnusedIncludes: Strict
  MissingIncludes: Strict
ClangTidy:
  Add: ["bugprone-*", "performance-*", "modernize-*", "clang-analyzer-*"]
  Remove: ["modernize-use-trailing-return-type", "readability-identifier-length"]
InlayHints:
  Designators: true
  ParameterNames: true
  DeducedTypes: true
커널 전용 clangd 팁:
  • CONFIG_ 매크로가 정의되지 않아 진단 오류가 뜨면 CompileFlags.Add에 주요 CONFIG_ 매크로를 추가
  • 생성된 헤더(include/generated/*) 경로를 CompileFlags.Add: ["-Iinclude/generated"]로 추가
  • 인덱스 크기가 크면 Index.Background: Build 대신 Index.Background: Skip로 설정 후 수동 인덱싱

GNU Global (gtags): 빠른 기호 검색

gtags는 ctags/cscope 대안으로, 증분 업데이트와 파일명·심볼·정의·참조 4가지 검색 모드를 제공합니다. 대용량 코드베이스에서 grep보다 훨씬 빠릅니다.

# 설치
sudo apt install global  # Ubuntu/Debian
sudo dnf install global  # Fedora
pacman -S global  # Arch

# 커널 루트에서 인덱스 생성 (최초 1회, 수 분 소요)
gtags -v

# 증분 업데이트 (파일 수정 후)
gtags -u

# 사용 예
global -x sys_open        # 정의 검색
global -rx sys_open       # 참조 검색
global -s sys_open        # 심볼 검색
global -f drivers/net     # 파일 검색

에디터 연동:

rust-analyzer: Rust 커널 코드 탐색

Rust-for-Linux 코드(rust/, samples/rust/, 드라이버)를 탐색하려면 rust-analyzer가 필수입니다. 커널은 특수 타깃(riscv64gc-unknown-linux-kernel 등)을 사용하므로 표준 설정만으로는 불완전합니다.

# rustup으로 설치
rustup component add rust-analyzer

# 또는 최신 nightly 버전 (더 나은 커널 지원)
rustup toolchain install nightly
rustup component add rust-analyzer --toolchain nightly

# 커널 소스에서 rust-project.json 생성 (bindgen 포함)
./scripts/rust/gen_rust_project.py

.rust-analyzer 설정 (.vscode/settings.json 또는 프로젝트 루트 rust-analyzer.toml):

# rust-analyzer.toml
["rust-analyzer"]
rustc.source = "discover"
cargo.target = "x86_64-unknown-linux-gnu"  # host 타깃용 분석용
procMacro.enable = true
checkOnSave.command = "clippy"
checkOnSave.allTargets = false
inlayHints.typeHints.enable = true
inlayHints.chainingHints.enable = true
files.watcher = "client"

# 커널 전용 타깃도 추가 분석하려면
["rust-analyzer".cargo.extraEnv]
RUSTFLAGS = "--cfg kernel"
RUSTC_BOOTSTRAP = "1"
주의: rust-analyzer는 rust-project.json을 자동 감지합니다. 커널 루트에서 gen_rust_project.py를 실행하면 rust-project.json이 생성되어 rust-analyzer가 커널 타깃(arm64-unknown-linux-kernel 등)과 바인딩을 올바르게 인식합니다. 이 파일은 .gitignore에 있으므로 커밋하지 마세요.

에디터별 통합 설정 요약

에디터C/C++ (clangd)C/C++ (gtags)Rust (rust-analyzer)
VS Code clangd 익스텐션 (공식) GNU Global 익스텐션 rust-analyzer 익스텐션 (공식)
Neovim nvim-lspconfig + clangd gtags.vim / gtags-cscope nvim-lspconfig + rust_analyzer
Vim vim-lsp / coc.nvim gtags.vim (내장) coc-rust-analyzer
Emacs lsp-mode + clangd ggtags lsp-mode + rust-analyzer
Helix 내장 LSP (clangd) N/A 내장 LSP (rust-analyzer)
권장 조합: clangd (LSP) + gtags (폴백/파일 검색) 조합이 가장 실용적입니다. clangd가 정확한 정의·참조 점프를, gtags가 파일명·심볼명 빠른 검색과 clangd가 놓치는 매크로 정의를 보완합니다. Rust 코드는 rust-analyzer 단독으로 충분합니다.

소스 코드 읽기 가이드: 상세 설정 예시 →

에디터 설정

Vim, VS Code, Emacs, Neovim의 커널 개발 최적화 설정은 별도 페이지로 분리되었습니다.

에디터 설정 가이드 →

QEMU/KVM 가상 환경 설정

QEMU 설치, rootfs 생성, 커널 부팅, 빠른 테스트 루프, 부팅 실패 대응 등 QEMU/KVM 가상 환경의 상세 가이드는 별도 페이지로 분리되었습니다.

QEMU 가상 환경 가이드 →

virtme-ng: 빠른 커널 테스트

virtme-ng는 별도 rootfs 없이 호스트 파일시스템(Filesystem)을 공유하여 빌드한 커널을 즉시 부팅하는 도구입니다. 설치, 사용법, QEMU와의 비교는 QEMU 가이드에서 확인할 수 있습니다.

QEMU 가이드: virtme-ng 섹션 →

initramfs 직접 생성

BusyBox 기반 initramfs 생성, 커널 내장 initramfs, 고급 구성 등 상세 가이드는 QEMU 페이지에서 확인할 수 있습니다.

QEMU 가이드: initramfs 섹션 →

BusyBox 멀티콜 바이너리 아키텍처, 애플릿 시스템 등 심층 내용은 BusyBox 종합 가이드를 참고하세요.

크로스 컴파일 환경

ARM, ARM64, RISC-V 크로스 컴파일 환경 구축은 별도 페이지로 분리되었습니다.

크로스 컴파일 환경 가이드 →

GDB/KGDB 디버거 설정

GDB/KGDB를 이용한 커널 소스 레벨 디버깅 — QEMU-GDB 연동 워크플로, GDB 명령어, KGDB 실제 하드웨어 디버깅 등 상세 가이드는 별도 페이지로 분리되었습니다.

디버깅 가이드 → | QEMU 가이드: 커널 디버깅 섹션 →

디버그 커널 설정 옵션 총정리

커널 디버그 CONFIG 옵션 카테고리별 정리, 목적별 프로필, Sanitizer 조합 가이드는 별도 페이지로 분리되었습니다.

디버그 설정 옵션 가이드 →

빌드 속도 최적화

ccache (컴파일러 캐시)

ccache는 컴파일 결과를 캐싱하여 재빌드 속도를 크게 향상시킵니다.

# ccache 설치 (이미 위에서 설치됨)
sudo apt install ccache

# ccache 캐시 크기 설정 (기본 5GB, 10GB 권장)
ccache -M 10G

# ccache 통계 확인
ccache -s

# 커널 빌드 시 ccache 사용
make CC="ccache gcc" -j$(nproc)

# 또는 PATH에 ccache 심볼릭 링크 추가
export PATH="/usr/lib/ccache:$PATH"
make -j$(nproc)

distcc (분산 컴파일)

여러 머신을 사용하여 병렬로 컴파일하면 빌드 시간을 대폭 단축할 수 있습니다.

# 서버 머신에서 distccd 실행
sudo apt install distcc
distccd --daemon --allow 192.168.1.0/24

# 클라이언트 머신에서 빌드
export DISTCC_HOSTS="localhost 192.168.1.100 192.168.1.101"
make CC="distcc gcc" -j16
주의: 분산 빌드는 네트워크 지연(Latency)과 전처리 비용에 따라 오히려 느려질 수 있습니다. 먼저 ccache만으로 이득을 확인한 뒤, 대형 소스 트리에서만 distcc를 추가하는 순서가 안전합니다.

빌드 환경 성능 튜닝

커널 빌드 성능은 디스크 I/O, 병렬 작업 수, 캐시 효율에 크게 좌우됩니다. 아래 기법을 조합하면 빌드 시간을 크게 단축할 수 있습니다.

tmpfs 빌드 (RAM 디스크)

# 별도 빌드 디렉토리를 tmpfs에 마운트
sudo mkdir -p /mnt/kbuild
sudo mount -t tmpfs -o size=15G tmpfs /mnt/kbuild

# 소스와 빌드 디렉토리 분리 (O= 옵션)
cd /home/user/linux
make O=/mnt/kbuild defconfig
make O=/mnt/kbuild -j$(nproc)

# 영구 설정: /etc/fstab에 추가
# tmpfs /mnt/kbuild tmpfs size=15G,mode=1777 0 0
주의: tmpfs는 RAM을 사용합니다. 최소 32GB RAM에서 15GB 할당을 권장합니다. 시스템 메모리가 부족하면 OOM Killer가 작동할 수 있습니다.

병렬 작업 수 최적화

# 기본: CPU 코어 수
make -j$(nproc)

# 코어 수 + 2 (I/O 대기 보상)
make -j$(( $(nproc) + 2 ))

# 메모리 제한 고려: 코어당 2GB 필요 (LTO 시)
# 16GB RAM, 8코어 → -j8이 안전
# 8GB RAM, 8코어 → -j4 권장

# 백그라운드 빌드 (낮은 우선순위)
nice -n 19 ionice -c3 make -j$(nproc)

증분 빌드 최적화

기법 명령 효과
단일 파일 빌드 make drivers/net/my_driver.o 컴파일 오류만 빠르게 확인
단일 디렉토리 빌드 make drivers/net/ 서브시스템 전체 빌드
모듈만 빌드 make modules vmlinux 재링크 건너뜀
ccache + 분리 빌드 make CC="ccache gcc" O=build/ 캐시 히트로 재빌드 10초 이내
전처리만 확인 make drivers/net/my_driver.i 매크로(Macro) 전개 결과 확인
어셈블리(Assembly) 확인 make drivers/net/my_driver.s 컴파일러 출력 코드 확인
환경별 커널 빌드 소요 시간 비교 (로그 스케일 가로 막대 그래프) 빌드 시간 비교 (x86_64 defconfig, 8코어 기준) 기본 HDD -j1, 전체 빌드 ~45분 (2700초) SSD -j8, 전체 빌드 ~8분 (480초) SSD + ccache -j8, 재빌드 ~1분 (60초) tmpfs + ccache -j8, 재빌드 ~30초 virtme-ng 빌드 + 부팅 ~15초 증분 빌드 단일 파일 수정 ~10초 10초 30초 1분 5분 15분 45분 소요 시간 (로그 스케일) ※ 가로축은 로그 스케일 — 막대 길이는 시간의 로그값에 비례하며, 초 단위의 작은 차이도 함께 비교하기 위한 것임 ※ 수치는 x86_64 defconfig, 8코어 환경에서의 참고용 예시(측정 환경·하드웨어에 따라 크게 달라짐) 정확한 개별 빌드 시간은 디스크, 메모리, 커널 설정, 변경 범위에 따라 달라질 수 있음 핵심: SSD + ccache + 증분 빌드 조합이 대체로 실용적인 개발 환경
그림: 커널 빌드 성능 최적화 비교 — 환경별 빌드 시간 차이

정적 분석 도구

Sparse, Coccinelle, checkpatch.pl 등 커널 정적 분석 도구의 설치와 상세 사용법은 별도 페이지로 분리되었습니다.

개발 도구 가이드: 정적 분석 섹션 → | 코딩 스타일(Coding Style) 가이드 →

커널 셀프테스트 (kselftest)

커널 셀프테스트는 커널 기능의 회귀를 자동으로 검출하는 테스트 프레임워크입니다. tools/testing/selftests/에 서브시스템별 테스트가 있으며, 패치(Patch) 제출 전 관련 테스트를 실행하는 것이 좋습니다.

셀프테스트 실행

# 전체 셀프테스트 빌드 & 실행
make -C tools/testing/selftests run_tests

# 특정 서브시스템 테스트만 실행
make -C tools/testing/selftests TARGETS="net mm" run_tests

# 개별 테스트 빌드
make -C tools/testing/selftests/net

# 크로스 컴파일 셀프테스트
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \
  -C tools/testing/selftests TARGETS="bpf"

# 설치 (QEMU rootfs에 복사용)
make -C tools/testing/selftests TARGETS="net" \
  INSTALL_PATH=/path/to/rootfs/kselftest install

주요 테스트 타겟

타겟 테스트 영역 선행 조건
bpf BPF/eBPF 프로그램 CONFIG_BPF_SYSCALL, clang/llvm
net 네트워킹 스택 CONFIG_NET
mm 메모리 관리(Memory Management) CONFIG_USERFAULTFD
cgroup 컨트롤 그룹 CONFIG_CGROUPS
futex Futex 동기화 CONFIG_FUTEX
seccomp Seccomp 필터 CONFIG_SECCOMP
kvm KVM 가상화 CONFIG_KVM
filesystems 파일시스템 공통 다양한 FS CONFIG
rust Rust 커널 모듈 CONFIG_RUST, LLVM 필수
sched_ext 확장 스케줄러(Extensible Scheduler) CONFIG_SCHED_CLASS_EXT (v6.12+)
landlock Landlock 샌드박스(Sandbox) CONFIG_SECURITY_LANDLOCK

테스트 작성 기본 패턴

// tools/testing/selftests/my_subsystem/my_test.c
#include "../kselftest_harness.h"

/* 기본 테스트 */
TEST(my_basic_test)
{
    int result = do_something();

    /* 성공 조건 확인 */
    ASSERT_EQ(result, 0);
    ASSERT_NE(result, -1);
    ASSERT_GT(result, -1);
    EXPECT_TRUE(result >= 0);
}

/* 파라미터화된 테스트 */
FIXTURE(my_fixture)
{
    int fd;
};

FIXTURE_SETUP(my_fixture)
{
    self->fd = open("/dev/mydev", O_RDWR);
    ASSERT_GE(self->fd, 0);
}

FIXTURE_TEARDOWN(my_fixture)
{
    close(self->fd);
}

TEST_F(my_fixture, read_test)
{
    char buf[64];
    ssize_t n = read(self->fd, buf, sizeof(buf));
    ASSERT_GT(n, 0);
}

TEST_HARNESS_MAIN
# tools/testing/selftests/my_subsystem/Makefile
TEST_GEN_PROGS := my_test
include ../lib.mk
kselftest 활용 팁:
  • KSFT_SKIP 반환으로 선행 조건 미충족 시 테스트 건너뛰기
  • make -C tools/testing/selftests TARGETS="net" summary=1로 결과 요약
  • QEMU에서 실행 시 INSTALL_PATH로 rootfs에 테스트 복사 후 실행
  • CI 파이프라인(Pipeline)에 셀프테스트 포함하여 자동 회귀 검사

KUnit 단위 테스트 프레임워크

KUnit은 커널 내장 단위 테스트 프레임워크(v5.5+)로, kselftest가 유저 공간(User Space)에서 커널을 검증하는 반면 KUnit은 커널 공간(Kernel Space) 안에서 직접 실행됩니다. v6.12 이후 Rust 커널 모듈의 KUnit 연동도 지원됩니다.

KUnit 빠른 실행

# 모든 KUnit 테스트 실행 (UML 기반, QEMU 불필요)
./tools/testing/kunit/kunit.py run

# 특정 테스트 스위트만 실행
./tools/testing/kunit/kunit.py run "list_test"

# 특정 아키텍처에서 실행
./tools/testing/kunit/kunit.py run --arch=arm64 --cross_compile=aarch64-linux-gnu-

# QEMU에서 기존 커널로 실행 (모듈로 빌드)
./scripts/config --module KUNIT
./scripts/config --module KUNIT_EXAMPLE_TEST
make -j$(nproc) modules
# QEMU 부팅 후:
modprobe kunit_example_test

KUnit 테스트 작성법, Fixture, 파라미터화 테스트, Rust KUnit 연동, kselftest와의 차이점 비교는 별도 페이지에서 확인할 수 있습니다.

개발 도구 가이드: KUnit 섹션 → | Rust 커널: KUnit 테스트 →

일반적인 개발 워크플로

커널 개발의 핵심은 수정 → 빌드 → 부팅 → 디버깅 반복 루프를 최대한 빠르게 돌리는 것입니다. 아래 다이어그램은 이 루프 전체를 보여주며, 이후 단계별 목록이 각 단계의 "왜?"를 설명합니다.

커널 개발 피드백 루프 — 수정→빌드→부팅·테스트→디버깅 ① 코드 수정 vim · VS Code · Emacs drivers/ mm/ net/ fs/ ② 빌드 · ccache make -j$(nproc) → bzImage 빠른 증분 빌드 ③ 부팅 · 테스트 (virtme-ng) vng · QEMU/KVM 부팅 수 초 kselftest · KUnit 실행 버그 발견 모든 테스트 통과 ④ 디버깅 GDB · KASAN · ftrace printk / dmesg 분석 ⑤ 패치 제출 git format-patch get_maintainer.pl → 메일 전송 재수정 ccache + virtme-ng 조합: 데스크톱급 x86_64 기준, 이 루프 한 바퀴가 총 1분 이내
그림: 커널 개발 피드백 루프 — ccache + virtme-ng 조합으로 데스크톱급 x86_64 기준 총 사이클을 1분 이내로 단축 가능
  1. 코드 수정
    # 메인라인 클론 및 브랜치 생성
    git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    cd linux
    git checkout -b my-feature
    
    # 에디터로 코드 수정
    vim drivers/my_driver.c
    
    # (선택) 코드 탐색 인덱스 생성
    make tags cscope
    ./scripts/clang-tools/gen_compile_commands.py

    왜? 메인라인 Linus 트리를 기준으로 작업해야 패치 제출 시 충돌이 최소화됩니다. 기능별 브랜치를 사용하면 여러 패치를 동시에 개발하고 독립적으로 git format-patch를 생성할 수 있습니다. compile_commands.json은 clangd·ccls·clang-tidy가 커널의 복잡한 매크로와 조건부 컴파일을 올바르게 해석하도록 돕습니다.

  2. 빌드
    make defconfig
    ./scripts/config --enable DEBUG_INFO
    make -j$(nproc)

    왜? defconfig는 현재 아키텍처의 검증된 기본값으로, 옵션을 하나씩 고르는 수고 없이 바로 빌드·부팅 가능한 커널을 생성합니다. DEBUG_INFO를 추가하면 GDB에서 소스 라인 단위 디버깅이 활성화됩니다. 증분 빌드(변경된 파일만 재컴파일)와 ccache 조합이면 단일 파일 수정 후 재빌드는 매우 빠르게 완료됩니다.

  3. 부팅·테스트
    # virtme-ng (가장 빠름)
    vng --arch x86_64
    
    # 또는 QEMU/KVM
    qemu-system-x86_64 -kernel arch/x86/boot/bzImage ...

    왜? virtme-ng는 커널 이미지를 바로 실행환경에서 부팅해 별도 가상 머신 설정 없이 테스트할 수 있습니다. 데스크톱급 x86_64 환경에서 QEMU 부팅까지 합쳐 1분 안에 루프를 완성할 수 있으며, kselftest·KUnit으로 자동화된 테스트도 실행합니다.

  4. 디버깅
    # printk / dmesg 분석
    dmesg | tail -50
    
    # GDB 디버깅 (CONFIG_DEBUG_INFO 필요)
    gdb vmlinux

    왜? 테스트 실패 시 GDB·KASAN·ftrace·printk/dmesg를 활용해 근본 원인을 추적합니다. 버그를 수정하면 ① 코드 수정으로 돌아가 루프를 반복합니다.

  5. 패치 제출
    # 코딩 스타일 검사
    ./scripts/checkpatch.pl --file drivers/my_driver.c
    
    # 정적 분석 (sparse)
    make C=2 drivers/my_driver.o
    
    # 패치 생성 및 커밋
    git add drivers/my_driver.c
    git commit -s
    git format-patch -1

    왜? 커널 메인테이너는 스타일 오류가 있는 패치를 즉시 반려합니다. checkpatch.pl이 오류·경고 0건인지, sparse로 정적 분석이 통과했는지 확인 후 format-patch로 메일 발송 형식의 패치 파일을 생성합니다. -s 옵션은 Signed-off-by 태그를 자동 추가합니다. 패치가 반려되면 리뷰 피드백을 반영해 ① 코드 수정 단계로 돌아가 루프를 반복합니다.

Git 커널 패치 워크플로

리눅스 커널 이메일 기반 패치 워크플로 — git format-patch, git send-email, get_maintainer.pl, b4 도구의 상세 사용법은 별도 페이지로 분리되었습니다.

커널 패치 제출 가이드 →

git bisect (회귀 추적)

특정 커밋에서 버그가 도입된 시점을 이진 탐색으로 찾습니다. 수천 개의 커밋 중에서도 log₂(N) 번의 테스트로 원인 커밋을 특정할 수 있습니다.

# bisect 시작
git bisect start

# 현재(버그 있음) = bad, 정상 동작 커밋 = good
git bisect bad HEAD
git bisect good v6.6

# Git이 중간 커밋을 체크아웃 → 테스트 → good/bad 반복
# 빌드 & 테스트
make -j$(nproc) && qemu-system-x86_64 ...
git bisect good   # 또는 git bisect bad

# 자동 bisect (스크립트로 자동화)
git bisect start HEAD v6.6
git bisect run ./test-script.sh

# bisect 종료 & 정리
git bisect reset
Git 커널 패치 워크플로 로컬 작업 (①~④) 리뷰 사이클 (⑤~⑦) 업스트림 수용·릴리스 (⑧~⑪) ① 코드 수정 git checkout -b fix/xxx 코드 편집 (vim 등) make -j$(nproc) 빌드 QEMU 부팅 동작 확인 ② 커밋 작성 git add 변경 파일 git commit -s Signed-off-by 자동 삽입 제목 50자 · 본문 72자 ③ 스타일 검사 ./scripts/checkpatch.pl make W=1 · C=1 (sparse) make coccicheck 모든 경고 해결 후 통과 ④ 패치 파일 생성 git format-patch -1 HEAD 0001-xxx.patch 생성 scripts/get_maintainer.pl 수신자(CC 목록) 확정 ⑤ 메일링 리스트 전송 git send-email 또는: b4 send To: 메일링 리스트 Cc: 메인테이너·리뷰어 ⑥ 메인테이너·리뷰어 코드 리뷰 패치를 직접 읽고 빌드·부팅 테스트 수행 문제 없으면 Reviewed-by: / Acked-by: 회신 수정 필요 시 피드백과 함께 반려(NAK) 0-day CI 등 자동화 테스트도 병행 수행 ⑦ 수정 반영 후 재전송 (v2, v3 …) 피드백을 반영해 수정 커밋 추가 git format-patch -v2 (-v3 …) 버전별 변경 로그(Changelog) 작성 완료 후 다시 ⑤ 전송 단계로 수정 요청 시 ⑦로 되돌아가 재전송 반복 — 대부분 몇 차례의 수정으로 수렴 승인 (Reviewed-by / Acked-by) ⑧ 서브시스템 트리에 적용 메인테이너 트리에 패치 머지 예: net-next, drm-next, tty.tree 리뷰 태그(Reviewed-by 등) 수록 Cc: stable → 안정 브랜치 백포트 ⑨ linux-next 통합 검증 전체 서브시스템 트리 통합 매일 전체 빌드·부팅 테스트 충돌과 회귀를 조기에 발견 문제 발생 시 담당 트리에서 제외 ⑩ mainline 머지 머지 윈도우 약 2주간 오픈 메인테이너 pull request 전송 Linus 트리(mainline)에 병합 병합 후 rc1부터 안정화 진행 ⑪ 정식 릴리스 rc1 → … → rcN 안정화 반복 v6.x 정식 버전 릴리스 이후 stable 브랜치 유지보수 다음 개발 사이클이 다시 시작 참고 — ⑤ 단계에서 실제 발송되는 패치 이메일의 구조 Subject: [PATCH v2 1/2] subsystem: 한 줄 요약 (50자 이내, 마침표 없음) 본문 — 무엇을 왜 수정했는지 설명(줄당 72자) | Fixes: abc1234 ("원인 커밋") Signed-off-by: 홍길동 <hong@example.com> · Cc: stable@vger.kernel.org (stable 백포트 시)
그림: Git 커널 패치 워크플로 — 코드 수정부터 업스트림 릴리스까지
커밋 메시지 규칙:
  • 제목: subsystem: 변경 요약 (50자 이내, 마침표 없음)
  • 본문: 왜 변경이 필요한지 설명 (72자/줄)
  • Signed-off-by: DCO(Developer Certificate of Origin) 동의 필수 (git commit -s)
  • Fixes: 버그 수정 시 원인 커밋 SHA 참조
  • Cc: stable 백포트 요청 시 Cc: stable@vger.kernel.org

트러블슈팅 플레이북

아래 순서대로 점검하면 환경 문제를 빠르게 축소할 수 있습니다. 핵심은 문제 범위를 한 단계씩 좁히는 것입니다.

  1. 도구 문제 분리: gcc --version, make --version, ld --version
  2. 설정 문제 분리: make mrproper && make defconfig로 최소 상태 확인
  3. 소스 문제 분리: 같은 커밋을 깨끗한 트리에서 다시 빌드
  4. 런타임 문제 분리: QEMU에서 재현되는지 먼저 확인
  5. 디버깅 단계 진입: GDB 브레이크포인트와 부팅 로그를 함께 확보
오류 메시지 예시 우선 점검 대응
No rule to make target ... 빌드 트리 오염 여부 make mrproper 후 defconfig부터 재시작(Reboot)
fatal error: openssl/... not found 개발 헤더 누락 libssl-dev 또는 openssl-devel 설치
pahole not found dwarves 패키지 설치 여부 dwarves/pahole 설치 후 재빌드
undefined reference ... 툴체인/설정 불일치 ARCH/CROSS_COMPILE/CONFIG 조합 재확인
QEMU 패닉 후 즉시 종료 로그 확보 실패 -nographic + panic=-1 + 로그 파일 저장
로그 수집 최소 세트: 빌드 로그(build.log), QEMU 부팅 로그(qemu-boot.log), 커널 설정(.config), 커밋 해시(Hash)를 항상 함께 보관하세요. 이 네 가지가 있으면 대부분의 환경 문제를 재현하고 분석할 수 있습니다.

고급 트러블슈팅

오류 메시지 / 증상 원인 해결
BTF: .tmp_vmlinux.btf: pahole ... not found CONFIG_DEBUG_INFO_BTF 활성화 + pahole 미설치 sudo apt install dwarves 또는 CONFIG_DEBUG_INFO_BTF=n
zstd: command not found 모듈 압축에 zstd 필요 sudo apt install zstd
GDB Remote 'g' packet reply is too long GDB 아키텍처 불일치 set arch i386:x86-64 또는 gdb-multiarch 사용 (상세)
clangd compile_commands.json not found 컴파일 DB 미생성 ./scripts/clang-tools/gen_compile_commands.py 실행
ccache cache miss 비율 높음 설정 변경, 캐시 크기 부족 ccache -M 20G, KBUILD_BUILD_TIMESTAMP 고정
QEMU Could not access KVM kernel module KVM 모듈 미로드 또는 권한 부족 sudo modprobe kvm_intel, sudo usermod -aG kvm $USER
KASAN BUG: KASAN: slab-out-of-bounds 버퍼(Buffer) 오버플로(Buffer Overflow) 감지 보고된 스택 트레이스에서 접근 위치 확인 후 경계 검사 추가
LOCKDEP possible circular locking 데드락 위험 감지 잠금(Lock) 획득 순서 재검토, 보고된 체인 분석
Kernel panic - not syncing: Attempted to kill init! PID 1(init) 프로세스(Process) 종료 initramfs의 init 스크립트가 exec /bin/sh로 끝나는지 확인
No working init found init 실행 파일 없음 rdinit=/init 파라미터 확인, init에 실행 권한(chmod +x) 확인

환경 진단 스크립트

#!/bin/bash
# kernel-env-check.sh - 커널 개발 환경 진단

echo "=== 커널 개발 환경 진단 ==="
echo

# 필수 도구
echo "[필수 도구]"
for cmd in gcc make git flex bison bc; do
  if command -v $cmd >/dev/null 2>&1; then
    echo "  ✓ $cmd: $($cmd --version 2>&1 | head -1)"
  else
    echo "  ✗ $cmd: 미설치"
  fi
done

# 라이브러리
echo
echo "[필수 라이브러리]"
for lib in libelf openssl; do
  if pkg-config --exists $lib 2>/dev/null; then
    echo "  ✓ $lib: $(pkg-config --modversion $lib)"
  else
    echo "  ✗ $lib: 미설치 또는 dev 패키지 필요"
  fi
done

# 선택 도구
echo
echo "[선택 도구]"
for cmd in clangd ctags cscope qemu-system-x86_64 gdb ccache sparse; do
  if command -v $cmd >/dev/null 2>&1; then
    echo "  ✓ $cmd"
  else
    echo "  - $cmd: 미설치 (선택)"
  fi
done

# KVM
echo
echo "[KVM 지원]"
if [ -e /dev/kvm ]; then
  echo "  ✓ /dev/kvm 존재"
  if [ -r /dev/kvm ] && [ -w /dev/kvm ]; then
    echo "  ✓ 현재 사용자 접근 가능"
  else
    echo "  ✗ 권한 부족: sudo usermod -aG kvm \$USER"
  fi
else
  echo "  ✗ /dev/kvm 없음: BIOS에서 가상화 활성화 필요"
fi

# 디스크/메모리
echo
echo "[시스템 리소스]"
echo "  RAM: $(free -h | awk '/Mem:/{print $2}')"
echo "  디스크 여유: $(df -h . | awk 'NR==2{print $4}')"
echo "  CPU 코어: $(nproc)"

추가 팁

디스크 공간: 커널 소스는 약 3GB, 빌드 산출물은 10GB 이상 차지합니다. SSD에 충분한 공간을 확보하세요.
RAM: 최소 8GB, 권장 16GB 이상. 병렬 빌드(-j 옵션)는 메모리를 많이 소비합니다. OOM 발생 시 병렬도를 낮추세요.
커널 버전 관리: 여러 커널 버전을 동시에 개발하는 경우, git worktree를 사용하면 편리합니다.
# 현재 mainline 트리에서 별도 작업 디렉토리 추가
git worktree add ../linux-mainline master

# linux-next 트리 추가
git remote add linux-next https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
git fetch linux-next master
git worktree add ../linux-next linux-next/master
안정 커널(stable)은 별도 stable remote에서 원하는 linux-6.x.y 유지보수 브랜치를 명시적으로 fetch한 뒤 worktree를 추가하세요.
빠른 부팅 테스트: initramfs를 만들기 전에도 early boot 로그와 패닉 지점까지는 빠르게 확인할 수 있습니다. 실제 initramfs를 붙이는 절차는 QEMU 가이드의 initramfs 섹션을 참고하세요.
make defconfig
make -j$(nproc)
qemu-system-x86_64 -kernel arch/x86/boot/bzImage \
  -append "console=ttyS0 panic=-1" \
  -nographic

Docker/Podman 컨테이너(Container) 개발 환경

컨테이너 기반 개발 환경은 호스트 시스템을 오염시키지 않으면서 재현 가능한 빌드 환경을 제공합니다. 팀 전체가 동일한 툴체인 버전을 사용하도록 강제할 수 있어, "내 머신에서는 빌드되는데" 문제를 완전히 차단합니다.

컨테이너 개발의 장점

항목 호스트 직접 설치 컨테이너 환경
재현성 호스트 업데이트에 따라 깨질 수 있음 Dockerfile 고정으로 완전 재현
다중 툴체인 버전 충돌 위험 이미지별 독립 환경
정리 패키지 잔여물 누적 컨테이너 삭제로 깔끔 정리
CI 연동 CI와 로컬 환경 불일치 동일 이미지로 CI/로컬 통일
크로스 컴파일 복잡한 멀티 아키텍처 설정 아키텍처별 전용 이미지

커널 빌드용 Dockerfile

# Dockerfile.kernel-dev
FROM ubuntu:24.04

LABEL maintainer="kernel-dev"
LABEL description="Linux kernel development environment"

# 비대화형 설치
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Seoul

# 필수 빌드 도구
RUN apt-get update && apt-get install -y \
    build-essential gcc g++ make \
    git flex bison pkg-config \
    libelf-dev libssl-dev \
    bc libncurses-dev \
    cpio rsync kmod \
    dwarves sparse ccache \
    \
    # 코드 탐색
    universal-ctags cscope \
    clangd clang lld llvm \
    \
    # 가상화 & 디버깅
    qemu-system-x86 qemu-system-arm qemu-system-misc \
    gdb gdb-multiarch \
    \
    # 크로스 컴파일
    gcc-aarch64-linux-gnu \
    gcc-arm-linux-gnueabihf \
    gcc-riscv64-linux-gnu \
    \
    # 유틸리티
    vim tmux ripgrep \
    python3 python3-pip \
    curl wget sudo \
    coccinelle \
    \
    && rm -rf /var/lib/apt/lists/*

# Rust 툴체인 (선택, CONFIG_RUST 사용 시)
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
    | sh -s -- -y --default-toolchain none \
    && . "$HOME/.cargo/env" \
    && cargo install --locked bindgen-cli
ENV PATH="/home/${USER}/.cargo/bin:${PATH}"

# ccache 설정
RUN ccache -M 20G
ENV PATH="/usr/lib/ccache:${PATH}"

# 비루트 사용자 생성
ARG USER=kdev
ARG UID=1000
RUN useradd -m -u ${UID} -s /bin/bash ${USER} \
    && echo "${USER} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

USER ${USER}
WORKDIR /home/${USER}/linux

CMD ["/bin/bash"]

컨테이너 빌드 및 실행

# 이미지 빌드
docker build -t kernel-dev -f Dockerfile.kernel-dev .

# 커널 소스를 마운트하여 실행
docker run -it --rm \
  -v $(pwd)/linux:/home/kdev/linux \
  -v kernel-ccache:/home/kdev/.cache/ccache \
  --device /dev/kvm \
  --name kernel-build \
  kernel-dev

# Podman 사용 시 (rootless)
podman run -it --rm \
  -v $(pwd)/linux:/home/kdev/linux:Z \
  -v kernel-ccache:/home/kdev/.cache/ccache:Z \
  --device /dev/kvm \
  --userns=keep-id \
  kernel-dev

# 컨테이너 안에서 빌드
make defconfig
make -j$(nproc)

# 컨테이너 안에서 QEMU 테스트
qemu-system-x86_64 \
  -kernel arch/x86/boot/bzImage \
  -append "console=ttyS0" \
  -nographic -enable-kvm -m 2G
볼륨 마운트(Mount) 전략:
  • 소스 코드: 호스트의 커널 소스를 바인드 마운트(Bind Mount) → 에디터는 호스트에서, 빌드는 컨테이너에서
  • ccache 캐시: named volume으로 컨테이너 재생성에도 캐시 유지
  • /dev/kvm: KVM 가속을 위해 디바이스 전달
  • 빌드 산출물: 소스 바인드 마운트에 포함되므로 호스트에서도 접근 가능

아키텍처별 컨테이너 전략

# ARM64 크로스 빌드 전용 컨테이너
docker run -it --rm \
  -v $(pwd)/linux:/home/kdev/linux \
  -e ARCH=arm64 \
  -e CROSS_COMPILE=aarch64-linux-gnu- \
  kernel-dev bash -c "make defconfig && make -j\$(nproc)"

# docker-compose.yml로 다중 아키텍처 동시 빌드
# docker compose up --parallel
# docker-compose.yml
services:
  x86-build:
    image: kernel-dev
    volumes:
      - ./linux:/home/kdev/linux
      - ccache-x86:/home/kdev/.cache/ccache
    command: bash -c "make x86_64_defconfig && make -j$(nproc)"

  arm64-build:
    image: kernel-dev
    volumes:
      - ./linux:/home/kdev/linux
      - ccache-arm64:/home/kdev/.cache/ccache
    environment:
      - ARCH=arm64
      - CROSS_COMPILE=aarch64-linux-gnu-
    command: bash -c "make defconfig && make -j$(nproc)"

  riscv-build:
    image: kernel-dev
    volumes:
      - ./linux:/home/kdev/linux
      - ccache-riscv:/home/kdev/.cache/ccache
    environment:
      - ARCH=riscv
      - CROSS_COMPILE=riscv64-linux-gnu-
    command: bash -c "make defconfig && make -j$(nproc)"

volumes:
  ccache-x86:
  ccache-arm64:
  ccache-riscv:
# arm64 부팅 테스트 (QEMU TCG 에뮬레이션)
docker run -it --rm \
  -v $(pwd)/linux:/home/kdev/linux \
  kernel-dev bash -c "qemu-system-aarch64 -M virt -cpu max -m 2G -kernel arch/arm64/boot/Image -nographic"

# riscv 부팅 테스트 (QEMU virt 머신 + OpenSBI)
docker run -it --rm \
  -v $(pwd)/linux:/home/kdev/linux \
  kernel-dev bash -c "qemu-system-riscv64 -M virt -m 2G -kernel arch/riscv/boot/Image -nographic"
Docker 기반 커널 개발 환경 아키텍처 호스트 시스템 1 에디터 (코드 편집) VS Code · Vim clangd · ctags Git (버전 관리) 커밋 · 브랜치 format-patch로 패치 제작 KVM 가속 디바이스 /dev/kvm 가상화 하드웨어 접근 커널 소스 트리 (단일 사본) 호스트 $(pwd)/linux · 컨테이너 /home/kdev/linux — 같은 디렉터리 공유 QEMU 실행 컨테이너에만 전달 --device /dev/kvm 옵션 사용 2 바인드 마운트 (읽기·쓰기 공유) Docker / Podman 컨테이너 x86_64 네이티브 빌드 GCC 13 Make · binutils GDB QEMU (KVM 가속) 3 make defconfig && make -j$(nproc) → bzImage · vmlinux 생성 4 QEMU 부팅 테스트 · GDB 디버깅 마운트: $(pwd)/linux · ccache-x86 · /dev/kvm ccache-x86 named volume · 영구 캐시 ARM64 크로스 빌드 aarch64-gcc Make · binutils gdb-multiarch QEMU (TCG 에뮬레이션) 3 ARCH=arm64 CROSS_COMPILE=aarch64-... → Image · dtb 생성 4 QEMU -M virt 부팅 테스트 마운트: $(pwd)/linux · ccache-arm64 ccache-arm64 named volume · 영구 캐시 RISC-V 크로스 빌드 riscv64-gcc Make · binutils gdb-multiarch QEMU · OpenSBI 3 ARCH=riscv CROSS_COMPILE=riscv64-... → Image · dtb 생성 4 QEMU -M virt 부팅 테스트 마운트: $(pwd)/linux · ccache-riscv ccache-riscv named volume · 영구 캐시 1 호스트에서 편집 2 소스·산출물 공유 3 컨테이너에서 빌드 4 QEMU 부팅 테스트
그림: Docker 기반 커널 개발 환경 아키텍처 — 호스트에서 편집, 컨테이너에서 빌드/테스트
주의사항:
  • UID 매핑(Mapping): 컨테이너 내부 UID와 호스트 UID가 다르면 소스 파일 권한 문제 발생 → --build-arg UID=$(id -u) 사용
  • 빌드 산출물 소유권: 컨테이너에서 생성한 파일의 소유자가 호스트와 다를 수 있음 → Podman의 --userns=keep-id 권장
  • SELinux: Fedora/RHEL에서는 바인드 마운트에 :Z 접미사 필요

원격 개발 환경

SSH 최적화, tmux, GNU Screen, VS Code Remote Development 설정은 별도 페이지로 분리되었습니다.

원격 개발 환경 가이드 →

커널 설정 전략

커널 설정(.config)은 4000개 이상의 옵션으로 구성됩니다. 목적에 맞는 설정 전략을 세우면 빌드 시간 단축과 디버깅 효율 향상을 동시에 달성할 수 있습니다. 설정 도구(menuconfig, nconfig, xconfig 등)의 상세 비교는 커널 빌드 시스템 페이지를 참고하세요.

Kconfig 시스템 — .config가 만들어지는 원리

커널 옵션이 4,000개 이상인 이유는 단순합니다. 커널은 수천 가지 하드웨어와 시나리오를 지원하며, 각 드라이버·서브시스템·보안 기능마다 "필요한 사람만 켜는" 스위치가 있기 때문입니다. 이 스위치 체계를 Kconfig라 부르며, Kconfig 파일 → menuconfig UI → .config 파일 → 빌드 순서로 동작합니다.

Kconfig 동작 흐름 — Kconfig 파일→menuconfig→.config→빌드 다시 열면 기존 .config 값 복원 1 Kconfig 파일들 arch/x86/Kconfig drivers/net/Kconfig net/Kconfig 옵션·의존성·기본값 정의 파싱 2 설정 도구 make menuconfig (TUI) make nconfig · xconfig make defconfig (기본값) 옵션 값을 선택·확정 저장 3 .config 파일 CONFIG_NET=y CONFIG_USB=m # CONFIG_SCSI is not set 각 옵션의 결정 값 저장 반영 4 Kbuild / make autoconf.h 자동 생성 obj-y / obj-m 결정 → vmlinux · *.ko 최종 커널과 모듈 생성 =y 빌트인 — vmlinux에 직접 포함 =m 모듈(.ko) — modprobe로 로드 not set 해당 옵션 제외(비활성)
그림: Kconfig 동작 흐름 — Kconfig 파일이 menuconfig를 거쳐 .config로, 그리고 최종 빌드 결과물로 이어지는 과정
.config 값의미결과언제 선택?
=y 빌트인(Built-in) vmlinux에 정적 포함, 부팅 시 자동 활성화 필수 드라이버·보안 기능, 모듈 로딩 불가 환경
=m 모듈(Module) .ko 파일 생성, 런타임(Runtime) 동적 로드 선택적 드라이버·실험 기능, 빌드 시간 절약
is not set 비활성화 컴파일 안 함, 코드 크기·빌드 시간 절약 불필요한 드라이버·사용하지 않는 기능
Kconfig 의존성 해결: 옵션 A가 depends on B로 선언된 경우, B가 활성화되지 않으면 A는 menuconfig에서 회색 처리됩니다. select B는 반대로 A를 켜면 B도 자동 활성화합니다. make oldconfig는 기존 .config에 새 커널 버전의 추가 옵션을 대화형으로 적용하며, make olddefconfig는 모두 기본값으로 자동 적용합니다.

목적별 설정 전략

커널 설정 전략 플로차트 목적이 무엇인가? 빠른 학습/실험 make tinyconfig → 최소 옵션 (500개 미만) → 빌드가 매우 빠름 → 부팅 불가 · 학습 전용 make allnoconfig → 모든 옵션 비활성화 기반 개발/디버깅 make defconfig → 아키텍처 기본 설정 → 빌드가 비교적 빠름 → QEMU 부팅 가능 디버깅 옵션 추가 + CONFIG_DEBUG_INFO + CONFIG_GDB_SCRIPTS 배포/하드웨어 대응 make localmodconfig → 현재 로드된 모듈 기반 → 불필요 드라이버 제거 → 빌드 시간 크게 절감 make localyesconfig → 모듈 대신 빌트인 전체 커버리지 테스트 make allyesconfig → 모든 옵션 활성화 → 빌드에 오랜 시간 소요 → 컴파일 에러 검출용 make allmodconfig → 가능한 모든 것을 모듈로 ./scripts/config를 활용한 자동화 예시 ./scripts/config --enable DEBUG_INFO # 개별 옵션 활성화 ./scripts/config --disable MODULE_SIG # 개별 옵션 비활성화 ./scripts/config --set-val NR_CPUS 4 # 정수 값 설정 ./scripts/config --set-str LOCALVERSION "-mykernel" # 문자열 값 설정 ./scripts/config --module BTRFS_FS # 모듈로 설정 (=m) ./scripts/config --state DEBUG_INFO # 현재 상태 조회
그림: 커널 설정 전략 플로차트 — 목적에 따른 최적 설정 방법 선택

설정 프래그먼트 관리

프로젝트별 설정 변경을 .config 직접 수정 대신 프래그먼트 파일로 관리하면 버전 관리와 재현이 쉬워집니다.

# 디버그 프래그먼트: debug.config
cat > debug.config <<'EOF'
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_GDB_SCRIPTS=y
CONFIG_FRAME_POINTER=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_LOCKDEP=y
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_KASAN=y
EOF

# 프래그먼트 적용: defconfig + 디버그 옵션
cd /path/to/linux
make defconfig
./scripts/kconfig/merge_config.sh .config debug.config

# 또는 KCONFIG_ALLCONFIG 사용
make KCONFIG_ALLCONFIG=debug.config alldefconfig
# 최소 QEMU 부팅 프래그먼트: qemu-minimal.config
cat > qemu-minimal.config <<'EOF'
CONFIG_PCI=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BLK=y
CONFIG_VIRTIO_NET=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_EXT4_FS=y
CONFIG_TMPFS=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
EOF
설정 관리 베스트 프랙티스:
  • 프래그먼트 파일을 Git에 커밋하여 팀과 공유
  • make savedefconfig로 현재 설정의 최소 diff를 defconfig로 저장
  • scripts/diffconfig로 두 .config 파일의 차이점만 추출
  • CI에서는 merge_config.sh로 베이스 + 프래그먼트 조합 자동화

컨테이너 기반 빌드와 TuxMake

현대적인 커널 개발 워크플로에서는 컨테이너를 사용해 빌드 환경을 격리하고 재현 가능하게 구성합니다. scripts/container는 커널 트리에 포함된 표준화된 컨테이너 빌드 스크립트이고, TuxMake는 커널 CI/CD 파이프라인을 위한 선언적 빌드 도구입니다.

scripts/container: 커널 내장 컨테이너 도구

Linux 6.1+ 부터 scripts/container 디렉토리에 커널 빌드용 컨테이너 이미지 생성·실행 스크립트가 포함되어 있습니다.

# 컨테이너 이미지 빌드 (Podman 또는 Docker 필요)
cd /path/to/linux
./scripts/container build

# 빌드된 이미지로 컨테이너 실행
./scripts/container run

# 컨테이너 내부에서 커널 빌드
make defconfig
make -j$(nproc)

# 특정 아키텍처용 컨테이너 빌드
./scripts/container build --arch=arm64
./scripts/container run --arch=arm64

# 사용자 정의 툴체인/이미지 지정
./scripts/container build --image=my-kernel-dev --toolchain=llvm
./scripts/container run --image=my-kernel-dev
scripts/container 구조:
  • build — 베이스 이미지(Ubuntu/Fedora/Arch 등)에서 커널 빌드에 필요한 모든 패키지를 설치한 이미지 생성
  • run — 소스 디렉토리를 마운트하고 ccache 볼륨을 공유해 컨테이너 실행
  • Dockerfile.* / Containerfile.* — 아키텍처별·툴체인별 정의 파일
  • Podman/Docker 양쪽 지원, rootless 실행 가능

실전 컨테이너 워크플로

# 1. 호스트에서 ccache 볼륨 생성 (최초 1회)
podman volume create kernel-ccache

# 2. 컨테이너 이미지 빌드 (LLVM/Clang 툴체인 포함)
./scripts/container build --toolchain=llvm

# 3. 소스 마운트 + ccache 공유로 컨테이너 진입
./scripts/container run \
  -v $(pwd):/home/kdev/linux:Z \
  -v kernel-ccache:/home/kdev/.cache/ccache:Z \
  --device /dev/kvm \
  --userns=keep-id

# 4. 컨테이너 내부에서 빌드
make LLVM=1 defconfig
make LLVM=1 -j$(nproc)

# 5. 컨테이너 내부에서 QEMU 테스트 (KVM 패스스루 필요)
qemu-system-x86_64 \
  -kernel arch/x86/boot/bzImage \
  -initrd initramfs.img \
  -append "console=ttyS0 root=/dev/vda rw" \
  -drive file=rootfs.ext4,format=raw,if=virtio \
  -nographic -m 2G -smp 2 \
  -enable-kvm

TuxMake: 선언적 커널 빌드 및 CI/CD

TuxMake(tuxmake.org)는 커널 빌드를 선언적으로 정의하고 다양한 아키텍처·툴체인·설정 조합을 매트릭스로 실행하는 도구입니다. KernelCI, GitLab CI, GitHub Actions 등 CI 시스템과 통합되어 커널 패치 검증 파이프라인의 표준으로 쓰입니다.

설치

# pip 설치 (Python 3.9+)
pip install tuxmake

# 또는 컨테이너로 실행 (별도 설치 불필요)
podman run --rm -v $(pwd):/kernel ghcr.io/tuxmake/tuxmake:latest \
  tuxmake --help

기본 사용법

# 기본 빌드 (x86_64, GCC, defconfig)
tuxmake

# 아키텍처·툴체인·설정 지정
tuxmake --arch=arm64 --toolchain=clang --config=defconfig

# 여러 조합 매트릭스 빌드
tuxmake \
  --arch=x86_64 --arch=arm64 --arch=riscv64 \
  --toolchain=gcc --toolchain=clang \
  --config=defconfig --config=allmodconfig

# 출력 아티팩트 지정
tuxmake --output-dir=out --target=bzImage --target=modules

선언적 빌드 설정 (.tuxmake.yaml)

# 프로젝트 루트에 .tuxmake.yaml 배치
targets:
  - bzImage
  - modules
  - dtbs

architectures:
  - x86_64
  - arm64
  - riscv64

toolchains:
  - gcc
  - clang
  - clang-nightly  # 최신 LLVM 스냅샷

configs:
  - defconfig
  - allmodconfig
  - tinyconfig

make_variables:
  KBUILD_BUILD_USER: "ci"
  KBUILD_BUILD_HOST: "tuxmake"
  LOCALVERSION: "-tuxmake"

environment:
  CCACHE_DIR: "/workspace/.ccache"
  KCFLAGS: "-Werror"

filter:
  include:
    - "drivers/net/*"
    - "fs/*"
  exclude:
    - "drivers/staging/*"

artifacts:
  keep:
    - "*.ko"
    - "vmlinux"
    - "System.map"
    - "bzImage"
    - "Image.gz"
    - "*.dtb"
  compress: true

CI/CD 파이프라인 통합 (GitHub Actions 예시)

# .github/workflows/kernel-build.yml
name: Kernel Build Matrix

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 60
    strategy:
      matrix:
        arch: [x86_64, arm64, riscv64]
        toolchain: [gcc, clang]
        config: [defconfig, allmodconfig]
        include:
          - arch: s390x
            toolchain: gcc
            config: defconfig
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Set up TuxMake
        run: |
          pip install tuxmake

      - name: Build kernel
        run: |
          tuxmake \
            --arch=${{ matrix.arch }} \
            --toolchain=${{ matrix.toolchain }} \
            --config=${{ matrix.config }} \
            --output-dir=out/${{ matrix.arch }}-${{ matrix.toolchain }}-${{ matrix.config }} \
            --target=bzImage --target=modules

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: kernel-${{ matrix.arch }}-${{ matrix.toolchain }}-${{ matrix.config }}
          path: out/${{ matrix.arch }}-${{ matrix.toolchain }}-${{ matrix.config }}/*
          retention-days: 7

KernelCI 연동

TuxMake는 KernelCI 파이프라인의 빌드 단계로 기본 통합됩니다. KernelCI에 패치를 제출하면 TuxMake가 다중 아키텍처·툴체인 매트릭스 빌드를 수행하고, 부팅 테스트(QEMU/실제 하드웨어)까지 자동 실행합니다.

# 로컬에서 KernelCI 스타일 전체 매트릭스 실행
tuxmake \
  --arch=x86_64 --arch=arm64 --arch=riscv64 --arch=s390x --arch=loongarch64 \
  --toolchain=gcc --toolchain=clang \
  --config=defconfig --config=allmodconfig --config=tinyconfig \
  --target=bzImage --target=modules --target=dtbs \
  --output-dir=kernelci-out
TuxMake 장점 요약:
  • 재현성: 컨테이너 기반 격리 빌드, 호스트 환경 영향 최소화
  • 선언적: YAML로 빌드 매트릭스 정의, 팀/CI 간 공유 용이
  • 매트릭스: 아키텍처 × 툴체인 × 설정 조합 자동 전개
  • 아티팩트 관리: 빌드 산출물 자동 압축·수집·업로드
  • CI 네이티브: GitHub Actions, GitLab CI, Jenkins, KernelCI 모두 지원
  • 필터링: 특정 서브시스템만 빌드해 피드백 루프 단축

컨테이너 빌드 베스트 프랙티스

원칙 구현
이미지 불변성
  • 베이스 이미지 태그 고정 (예: ubuntu:24.04 아닌 ubuntu@sha256:...)
  • 빌드 시점 도구 버전 기록 (Dockerfile에 ARG GCC_VERSION=13 등)
  • 캐시 계층 활용
  • 패키지 설치 레이어를 소스 복사 레이어 이전에 배치
  • ccache 볼륨을 별도 마운트로 분리 (이미지 크기 방지)
  • 권한 최소화
  • rootless 컨테이너 실행 (--userns=keep-id)
  • KVM만 필요 시 --device /dev/kvm만 패스스루
  • 재현 가능한 빌드
  • KBUILD_BUILD_TIMESTAMP 고정
  • SOURCE_DATE_EPOCH 설정
  • 툴체인 체크섬(Checksum) 검증
  • 아티팩트 분리
  • 빌드 컨테이너는 빌드만, 테스트 컨테이너는 별도 구성
  • 산출물은 볼륨/아티팩트 저장소로 내보내기
  • 참고 문서:

    참고자료

    공식 문서

    개발 도구

    커뮤니티 및 학습 리소스