커널 개발 환경 설정
Linux 커널 개발을 위한 개발 환경 구축 가이드: 필수 도구 설치, 에디터 설정, QEMU/KVM 가상 환경, 크로스 컴파일(Cross Compilation), GDB/KGDB 디버거 설정까지 완벽 정리.
핵심 요약
- 필수 도구 — gcc, make, git, flex, bison, libelf-dev 등 빌드에 필수적인 패키지를 먼저 설치합니다.
- 개발 보조 도구 — ctags, cscope, clangd 등으로 코드 탐색과 자동완성을 강화합니다.
- 가상 환경 — QEMU/KVM으로 안전하게 커널을 테스트하고 디버깅(Debugging)합니다.
- 크로스 컴파일 — ARM, ARM64, RISC-V 등 다른 아키텍처용 커널을 빌드합니다.
- 디버거 설정 — GDB/KGDB로 커널 소스 레벨 디버깅을 수행합니다.
단계별 이해
- 도구 설치
배포판에 맞는 패키지 관리자로 필수 도구를 설치합니다.왜? 커널 빌드는 GCC/Clang 컴파일러 외에도 flex·bison(파서 생성), libelf-dev(BPF 지원), bc(설정 스크립트 계산) 등 수십 개의 보조 도구가 얽혀 있습니다. 하나라도 빠지면
make defconfig단계에서 즉시 오류가 나므로, 첫 단계에서 올바른 패키지 세트를 설치해야 이후 과정이 막히지 않습니다. - 에디터 구성
선호하는 에디터에 코드 탐색 도구를 연동합니다.왜? 커널 소스는 약 3,500만 줄에 달합니다. ctags·cscope·clangd 없이
grep만으로 함수 정의와 호출 관계를 추적하면 수십 분이 걸립니다.compile_commands.json을 생성하면 에디터가 커널 매크로와 조건부 컴파일 분기까지 이해해 정확한 자동완성·점프가 가능해집니다. - 가상 환경 준비
QEMU/KVM으로 테스트용 가상 머신을 구성합니다.왜? 실제 하드웨어에서 커널 버그를 실험하면 시스템이 패닉(Panic)에 빠지거나 파일시스템이 손상될 수 있습니다. QEMU는 빌드한 커널 이미지를 격리된 환경에서 1초 안에 부팅하고, 크래시(Crash)가 발생해도 호스트에 영향을 주지 않습니다. GDB 원격 디버깅 포트도 QEMU 옵션 한 줄로 열립니다.
- 첫 빌드 실행
간단한 설정으로 커널을 빌드하고 부팅 테스트합니다.왜?
make defconfig는 현재 아키텍처의 합리적 기본값을 적용한 최소 빌드 설정입니다. 4,000개 이상의 옵션을 직접 건드리기 전에 이 설정으로 먼저 전체 빌드~QEMU 부팅 루프가 동작하는지 확인해야, 이후 옵션 추가 시 문제의 원인이 새 설정에 있다고 특정할 수 있습니다. - 디버거 연동
GDB와 QEMU를 연결하여 커널 디버깅 환경을 완성합니다.왜? 커널에서
printk만으로 디버깅하면 심각한 타이밍 의존 버그나 메모리 오염은 발견하기 어렵습니다.CONFIG_DEBUG_INFO로 빌드한 커널과 QEMU의-s -S옵션을 함께 사용하면, GDB에서 커널 소스 라인 단위 중단점·변수 조사·스택 트레이스를 실시간(Real-time)으로 수행할 수 있습니다.
환경 설계 원칙
커널 개발 환경은 단순 설치보다 재현성, 격리(Isolation), 검증 가능성이 중요합니다. 처음 한 번만 잘 구성하면 이후 실험 속도와 안정성이 크게 올라갑니다.
| 원칙 | 설명 | 실무 권장 |
|---|---|---|
| 재현성 | 같은 입력이면 같은 빌드 결과가 나와야 함 | 툴 버전 고정, 설정 파일(.config) 보관, 빌드 로그 아카이브 |
| 격리 | 호스트 시스템과 테스트 환경 분리 | QEMU/KVM 기본, 실제 장비는 후반 검증 단계에서만 사용 |
| 검증 가능성 | 문제 발생 시 원인 추적이 가능해야 함 | CONFIG_DEBUG_INFO, FRAME_POINTER, 로그 수집 자동화 |
| 점진적 확장 | 필수 도구부터 시작해 점진적으로 추가 | 필수(빌드) → 권장(탐색/가상화(Virtualization)) → 선택(분석/자동화) |
개발 도구 의존성 로드맵
커널 개발 환경은 여러 도구들이 계층적으로 연결된 생태계입니다. 아래 다이어그램은 각 도구의 역할과 의존 관계를 보여주며, 환경 구축 순서를 안내합니다.
환경 구축 권장 순서:
- 최소 환경 (1~2시간): Layer 0-1 + QEMU → 간단한 커널 빌드/부팅 가능
- 기본 개발 (반나절): + Layer 2A/2B → 코드 탐색 및 가상머신 테스트
- 완전한 환경 (1일): + Layer 3 → 디버깅 및 분석까지 모든 작업 가능
- 전문가 환경 (지속): + Layer 4 → 다중 아키텍처 개발 및 자동화
디스크 공간: 커널 소스 3GB + 빌드 결과 10GB + 가상머신 이미지 5GB = 최소 20GB 여유 필요
커널 빌드 파이프라인(Build Pipeline) 개요
make -j$(nproc) 한 줄 뒤에서는 수만 개의 C 소스 파일이 6단계 변환 과정을 거쳐 최종 vmlinux와 bzImage로 합쳐집니다.
이 흐름을 이해하면 "왜 이 도구가 필요한가?"가 자연스럽게 풀립니다.
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 |
| ⑤ 패키징 | objcopy, 커널 스크립트 |
vmlinux |
bzImage / Image.gz |
binutils, bc |
| ⑥ BTF 생성 | pahole |
vmlinux DWARF 정보 |
BTF 섹션 삽입 (BPF·eBPF 지원) | dwarves |
Makefile이 각 서브시스템 Makefile을 재귀 호출하여 병렬 컴파일을 조율합니다.
obj-y(빌트인), obj-m(모듈), obj-$(CONFIG_XXX)(조건부)로 빌드 대상을 선언하며, Kconfig 설정에 따라 어떤 파일을 컴파일할지 결정합니다.
개발 중에는 make drivers/net/my_driver.o처럼 단일 파일만 재컴파일하는 것도 가능합니다.
필수 개발 도구 설치
Linux 커널 빌드를 위해서는 컴파일러, 빌드 시스템, 버전 관리 시스템, 그리고 다양한 유틸리티가 필요합니다. 배포판별로 패키지 이름이 다를 수 있으므로 각 배포판에 맞는 명령어를 사용하세요.
Ubuntu / Debian 계열
# 필수 빌드 도구
sudo apt update
sudo apt install -y build-essential \
gcc make git pkg-config \
flex bison \
libelf-dev libssl-dev \
bc libncurses-dev \
cpio rsync
# 커널 문서 빌드 도구 (선택)
sudo apt install -y python3-sphinx \
texlive-latex-base texlive-latex-extra
# 추가 유틸리티
sudo apt install -y kmod dwarves \
sparse ccache
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)/헤더 버전 조합을 우선 확인하세요.
버전 관리 정책
커널 개발에서는 "최신 버전"보다 "팀 전체에서 동일한 조합"이 더 중요할 때가 많습니다. 도구 버전을 팀 기준으로 고정하면 재현 불가 버그를 크게 줄일 수 있습니다.
- 컴파일러: GCC/Clang 메이저 버전을 팀 단위로 맞춥니다.
- 정적 분석 도구: sparse, coccinelle 버전 차이는 경고 양상 차이를 만듭니다.
- 디버거: GDB 버전 차이는 Python 스크립트 동작 차이로 이어질 수 있습니다.
- 문서화: 프로젝트 루트에 "권장 도구 버전 표"를 두고 신규 인원이 그대로 따라오게 합니다.
도구 최소 버전 요구사항 (v6.14+ 기준)
아래는 커널 Documentation/process/changes.rst에 명시된 공식 최소 버전과 실무 권장 버전입니다. 최소 버전 미만의 도구로 빌드하면 경고 또는 오류가 발생합니다. 커널 버전마다 최소 버전이 상이할 수 있으므로, 실제 빌드하려는 커널 소스 트리에서 scripts/min-tool-version.sh를 실행하여 정확한 최소 버전을 확인하세요.
| 도구 | 최소 버전 (v6.14+) | 권장 버전 | 비고 |
|---|---|---|---|
| GCC | 8.1 | 13+ | v6.13까지는 5.1, v6.14+는 8.1 이상 필요. 실무에서는 12+ 권장 |
| Clang/LLVM | 15.0.0 | 19+ | v6.9~v6.13: 13.0.1, v6.14+: 15.0.0. AutoFDO는 LLVM 19+ 필요 |
| Rust (선택) | 1.78.0 | 최신 stable | CONFIG_RUST 활성화 시 필요, 커널 마이너 버전별로 요구 버전이 다를 수 있습니다 (v6.14: 1.83.0 권장) |
| bindgen (선택) | 0.65.1 | 최신 | Rust C 바인딩(Binding) 생성기, 커널 버전별 상이 |
| GNU Make | 4.0 | 4.4+ | v6.14+에서는 4.0 이상 필수 |
| binutils | 2.30 | 2.40+ | ld, as, ar, objcopy 포함. v6.14+에서는 2.30 이상 |
| flex | 2.5.35 | 2.6+ | |
| bison | 2.0 | 3.8+ | |
| pahole | 1.22 | 1.25+ | BTF 생성 (CONFIG_DEBUG_INFO_BTF), v6.14+에서는 1.22 이상 |
| Perl | 5 | 5.34+ | checkpatch.pl, 빌드 스크립트 |
| Python | 3.9.x | 3.10+ | Sphinx 문서, 여러 가지 빌드/테스트 스크립트. v6.14+에서는 3.9 이상 |
| openssl | 1.0.0 | 3.x | 모듈 서명 (CONFIG_MODULE_SIG) |
scripts/min-tool-version.sh로 현재 커널 소스가 요구하는 도구 최소 버전을 즉시 확인할 수 있습니다. 이 스크립트는 커널 소스 트리마다 해당하는 최소 버전을 반환하므로, 빌드하려는 커널 버전의 소스 디렉토리에서 실행하세요.
# 커널 소스 디렉토리에서 실행 (현재 트리의 최소 버전 반환)
scripts/min-tool-version.sh gcc # 예: 8.1 (v6.14+)
scripts/min-tool-version.sh llvm # 예: 15.0.0
scripts/min-tool-version.sh rustc # 예: 1.78.0
scripts/min-tool-version.sh bindgen # 예: 0.65.1
scripts/min-tool-version.sh binutils # 예: 2.30
rustc 1.85·bindgen 0.71.1 조합이 자주 언급됩니다. 다만 실제 요구값은 커널 트리의 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 \
elfutils-libelf-devel openssl-devel \
bc ncurses-devel \
cpio rsync
# 추가 유틸리티
sudo dnf install -y kmod dwarves \
sparse ccache
Arch Linux
# 필수 빌드 도구
sudo pacman -S --needed base-devel pkgconf \
gcc make git \
flex bison \
libelf openssl \
bc ncurses \
cpio rsync
# 추가 유틸리티
sudo pacman -S kmod pahole \
sparse ccache
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
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.12+, LLVM 19+ 필요)
# 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.12+, LLVM 19+) |
| Propeller | CONFIG_PROPELLER_CLANG |
포스트 링크 코드 레이아웃 최적화, AutoFDO와 병용 (v6.12+, LLVM 19+) |
GCC vs Clang 비교
| 항목 | GCC | Clang/LLVM |
|---|---|---|
| 역사 | 커널 공식 기본 컴파일러 | 4.x부터 공식 지원, Android 커널 기본 |
| 에러 메시지 | 간결 | 상세하고 컬러풀, 제안 포함 |
| 경고 수준 | 보수적 | 더 많은 잠재 문제 감지 |
| 크로스 컴파일 | 아키텍처별 별도 툴체인 | 단일 바이너리로 모든 아키텍처 |
| LTO | 지원 (느림) | ThinLTO로 빠르고 효율적 |
| 보안 기능 | 기본 | CFI, Shadow Call Stack 등 추가 |
| 빌드 속도 | 보통 | 비슷하거나 약간 빠름 |
| 플러그인 | GCC 플러그인 지원 | 미지원 (대안 기능 제공) |
# 양쪽 컴파일러로 빌드 테스트
# 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와 나란히 공식 kernelsupported 언어로, 새로운 커널 코드 작성에 있어 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.78.0
scripts/min-tool-version.sh bindgen # 예: 0.69.5
# 해당 버전 설치 및 필수 컴포넌트 추가
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
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 연동은 별도 페이지로 분리되었습니다.
코드 탐색 도구
ctags, cscope, clangd 등 코드 탐색 도구의 설치, 에디터 통합, 인덱스 관리 전략은 별도 페이지로 분리되었습니다.
에디터 설정
Vim, VS Code, Emacs, Neovim의 커널 개발 최적화 설정은 별도 페이지로 분리되었습니다.
QEMU/KVM 가상 환경 설정
QEMU 설치, rootfs 생성, 커널 부팅, 빠른 테스트 루프, 부팅 실패 대응 등 QEMU/KVM 가상 환경의 상세 가이드는 별도 페이지로 분리되었습니다.
virtme-ng: 빠른 커널 테스트
virtme-ng는 별도 rootfs 없이 호스트 파일시스템(Filesystem)을 공유하여 빌드한 커널을 즉시 부팅하는 도구입니다. 설치, 사용법, QEMU와의 비교는 QEMU 가이드에서 확인할 수 있습니다.
initramfs 직접 생성
BusyBox 기반 initramfs 생성, 커널 내장 initramfs, 고급 구성 등 상세 가이드는 QEMU 페이지에서 확인할 수 있습니다.
BusyBox 멀티콜 바이너리 아키텍처, 애플릿 시스템 등 심층 내용은 BusyBox 종합 가이드를 참고하세요.
크로스 컴파일 환경
ARM, ARM64, RISC-V 크로스 컴파일 환경 구축은 별도 페이지로 분리되었습니다.
GDB/KGDB 디버거 설정
GDB/KGDB를 이용한 커널 소스 레벨 디버깅 — QEMU-GDB 연동 워크플로, GDB 명령어, KGDB 실제 하드웨어 디버깅 등 상세 가이드는 별도 페이지로 분리되었습니다.
디버그 커널 설정 옵션 총정리
커널 디버그 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
ccache만으로 이득을 확인한 뒤, 대형 소스 트리에서만 distcc를 추가하는 순서가 안전합니다.
빌드 환경 성능 튜닝
커널 빌드 성능은 디스크 I/O, 병렬 작업 수, 캐시 효율에 크게 좌우됩니다. 아래 기법으로 빌드 시간을 50% 이상 단축할 수 있습니다.
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
병렬 작업 수 최적화
# 기본: 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 |
컴파일러 출력 코드 확인 |
정적 분석 도구
Sparse, Coccinelle, checkpatch.pl 등 커널 정적 분석 도구의 설치와 상세 사용법은 별도 페이지로 분리되었습니다.
커널 셀프테스트 (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
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와의 차이점 비교는 별도 페이지에서 확인할 수 있습니다.
일반적인 개발 워크플로
커널 개발의 핵심은 수정 → 빌드 → 부팅 → 디버깅 반복 루프를 최대한 빠르게 돌리는 것입니다. 아래 다이어그램은 이 루프 전체를 보여주며, 이후 단계별 목록이 각 단계의 "왜?"를 설명합니다.
- 소스 다운로드
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git cd linux왜? 메인라인 Linus 트리를 기준으로 작업해야 패치 제출 시 충돌이 최소화됩니다. 특정 서브시스템 패치라면 해당 메인테이너 트리를 대신 클론하는 것이 좋습니다.
- 브랜치 생성
git checkout -b my-feature왜?
master에서 직접 수정하면 업스트림 풀(pull) 시 충돌이 발생합니다. 기능별 브랜치를 사용하면 여러 패치를 동시에 개발하고 독립적으로git format-patch를 생성할 수 있습니다. - 설정 및 빌드
make defconfig ./scripts/config --enable DEBUG_INFO make -j$(nproc)왜?
defconfig는 현재 아키텍처의 검증된 기본값으로, 옵션을 하나씩 고르는 수고 없이 바로 빌드·부팅 가능한 커널을 생성합니다.DEBUG_INFO를 추가하면 GDB에서 소스 라인 단위 디버깅이 활성화됩니다. - 코드 탐색 인덱스 생성
make tags cscope ./scripts/clang-tools/gen_compile_commands.py왜?
compile_commands.json은 각 소스 파일이 어떤 플래그로 컴파일됐는지 기록합니다. clangd·ccls·clang-tidy가 이 파일을 읽어 커널의 복잡한 매크로와 조건부 컴파일을 올바르게 해석합니다. - 코드 수정 및 테스트
# 에디터로 코드 수정 vim drivers/my_driver.c # 재빌드 make -j$(nproc) # QEMU 테스트 qemu-system-x86_64 -kernel arch/x86/boot/bzImage ...왜? 증분 빌드(변경된 파일만 재컴파일)와 ccache 조합이면 단일 파일 수정 후 재빌드가 10초 내외입니다. QEMU 부팅까지 합쳐 1분 안에 루프를 완성할 수 있습니다.
- 코딩 스타일 검사
./scripts/checkpatch.pl --file drivers/my_driver.c왜? 커널 메인테이너는 스타일 오류가 있는 패치를 즉시 반려합니다. 제출 전 반드시
checkpatch.pl이 오류·경고 0건인지 확인해야 합니다. - 정적 분석
make C=2 drivers/my_driver.o왜?
C=2는 sparse로 해당 파일의 정적 분석을 수행합니다.__user포인터 오용, 락(Lock) 불균형, 잘못된 어노테이션 등 런타임에 드러나기 어려운 버그를 빌드 시점에 검출합니다. - 패치 생성
git add drivers/my_driver.c git commit -s git format-patch -1왜?
-s옵션은Signed-off-by: 이름 <이메일>태그를 자동 추가합니다. 커널 기여 프로세스는 모든 커밋에 이 태그를 요구하며,format-patch로 메일 발송 형식의 패치 파일을 생성합니다.
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
- 제목:
subsystem: 변경 요약(50자 이내, 마침표 없음) - 본문: 왜 변경이 필요한지 설명 (72자/줄)
- Signed-off-by: DCO(Developer Certificate of Origin) 동의 필수 (
git commit -s) - Fixes: 버그 수정 시 원인 커밋 SHA 참조
- Cc: stable 백포트 요청 시
Cc: stable@vger.kernel.org
트러블슈팅 플레이북
아래 순서대로 점검하면 환경 문제를 빠르게 축소할 수 있습니다. 핵심은 문제 범위를 한 단계씩 좁히는 것입니다.
- 도구 문제 분리:
gcc --version,make --version,ld --version - 설정 문제 분리:
make mrproper && make defconfig로 최소 상태 확인 - 소스 문제 분리: 같은 커밋을 깨끗한 트리에서 다시 빌드
- 런타임 문제 분리: QEMU에서 재현되는지 먼저 확인
- 디버깅 단계 진입: 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)"
추가 팁
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를 추가하세요.
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 \
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
- 소스 코드: 호스트의 커널 소스를 바인드 마운트(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:
- 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 파일 → 빌드 순서로 동작합니다.
.config로, 그리고 최종 빌드 결과물로 이어지는 과정| .config 값 | 의미 | 결과 | 언제 선택? |
|---|---|---|---|
=y |
빌트인(Built-in) | vmlinux에 정적 포함, 부팅 시 자동 활성화 | 필수 드라이버·보안 기능, 모듈 로딩 불가 환경 |
=m |
모듈(Module) | .ko 파일 생성, 런타임(Runtime) 동적 로드 |
선택적 드라이버·실험 기능, 빌드 시간 절약 |
is not set |
비활성화 | 컴파일 안 함, 코드 크기·빌드 시간 절약 | 불필요한 드라이버·사용하지 않는 기능 |
depends on B로 선언된 경우, B가 활성화되지 않으면 A는 menuconfig에서 회색 처리됩니다.
select B는 반대로 A를 켜면 B도 자동 활성화합니다.
make oldconfig는 기존 .config에 새 커널 버전의 추가 옵션을 대화형으로 적용하며, make olddefconfig는 모두 기본값으로 자동 적용합니다.
목적별 설정 전략
설정 프래그먼트 관리
프로젝트별 설정 변경을 .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로 베이스 + 프래그먼트 조합 자동화
참고자료
공식 문서
- HOWTO do Linux kernel development — 공식 커널 개발 시작 가이드
- Development Tools — 커널 개발 도구 종합 문서 (KASAN, sparse, coccinelle 등)
- Debugging kernel with GDB — QEMU+GDB 커널 디버깅 공식 가이드
- KASAN — Kernel Address Sanitizer (메모리 오류 검출)
- KCSAN — Kernel Concurrency Sanitizer (데이터 레이스 검출)
- UBSAN — Undefined Behavior Sanitizer (정의되지 않은 동작 검출)
- kmemleak — 커널 메모리 누수 검출기
- kselftest — 커널 셀프테스트 프레임워크
- ftrace — 함수 트레이싱 프레임워크 공식 문서
- Submitting Patches — 패치 제출 프로세스
- Linux Kernel Coding Style — 코딩 스타일 공식 규칙
- Kbuild Documentation — 커널 빌드 시스템(Kconfig, Makefile) 공식 문서
- Minimal Requirements — 커널 빌드에 필요한 도구 최소 버전 요구사항
- Rust in the Linux Kernel — Rust 커널 개발 공식 문서 (환경 설정, 코딩 가이드)
- KUnit — 커널 단위 테스트 프레임워크 (테스트 작성, 실행, CI 연동)
개발 도구
- QEMU Documentation — QEMU 공식 문서 (커널 테스트용 가상 머신)
- virtme-ng — 현재 커널을 QEMU에서 즉시 부팅하는 빠른 테스트 도구
- clangd — LSP 기반 코드 내비게이션 (정의 이동, 참조 찾기, 자동 완성)
- ccache — 컴파일 캐시 (반복 빌드 속도 5-10배 향상)
- Clang Cross Compilation — LLVM 크로스 컴파일 가이드
- perf Examples (Brendan Gregg) — perf 활용 예제 모음
- Cscope — 대규모 C 프로젝트 심볼 탐색 도구
- Universal Ctags — 소스 코드 태그 생성기 (함수/구조체(Struct) 정의 색인)
- Coccinelle — 의미 기반 패치 도구 (코드 패턴 일괄 변환)
- Sparse — C 의미 분석 도구 (__user, __iomem 어노테이션 검사)
커뮤니티 및 학습 리소스
- KernelNewbies — 초보자 위키, 환경 설정 가이드, 버전별 변경사항
- Kernel Build (KernelNewbies) — 커널 빌드 환경 설정 단계별 안내
- LWN.net — 커널 개발 뉴스, 도구, 인프라 관련 심층 분석
- Elixir Cross Referencer — 웹에서 커널 소스 버전별 탐색
- Greg KH YouTube — 커널 개발 환경 구성 및 개발 프로세스 강의
- Linux Performance (Brendan Gregg) — 리눅스 성능 분석 도구 종합 안내
관련 문서
- 커널 빌드 시스템 — Kbuild, Kconfig, 크로스 컴파일
- 디버깅 — 커널 디버깅 기법과 도구 상세 가이드
- 개발 도구 — GCC, Clang, 정적 분석 도구 종합
- 커널 모듈 — 모듈 빌드/테스트 환경
- QEMU — 가상 머신 기반 커널 테스트 상세 가이드
- 커널 보안 — 개발 환경 보안 설정
- 소스 코드 읽기 — 개발 환경 구축 후 소스 탐색 시작하기
- 코딩 스타일 — checkpatch.pl, 들여쓰기, 네이밍, 매크로 규칙
- 커널 개발 주의사항 — 흔히 발생하는 실수와 주의사항, 해결 방법 정리
- Rust 커널 프로그래밍 — Rust 추상화 계층, 드라이버 작성, KUnit 연동
- Rust 언어 기초~고급 — 소유권, 트레이트, async/await, no_std 기초
- 임베디드 빌드 시스템 — Buildroot/Yocto rootfs 구성 및 SDK 개발 환경