커널 개발 도구

Linux 커널 개발 생산성을 좌우하는 도구 체인을 한 번에 연결해 설명합니다. 컴파일러/링커(Linker) 설정, sparse·smatch·Coccinelle 기반 결함 탐지, checkpatch와 코딩 스타일(Coding Style) 검증, pahole/BTF를 통한 타입 정보 확인, QEMU·virtme·kselftest·KUnit 기반 재현 가능한 테스트, Git 패치(Patch) 리뷰/전송 흐름까지 실제 서브시스템 개발 루틴에 맞춰 상세히 다룹니다.

전제 조건: 개발 환경 설정커널 개발 주의사항 문서를 먼저 읽으세요. 개발 도구를 효과적으로 쓰려면 빌드 환경이 갖춰져 있고, 커널 개발 시 흔한 실수를 미리 알아두는 것이 핵심입니다.
일상 비유: 이 주제는 현장 사고 원인 조사와 비슷합니다. 증거를 순서 없이 모으면 결론이 흔들리듯이, 커널 디버깅(Debugging)도 관측 지점을 단계적으로 고정해야 빠르게 수렴합니다.

핵심 요약

  • 재현 우선 — 증상보다 재현 조건 고정이 먼저입니다.
  • 도구 선택 — 로그, 트레이스, 코어덤프 용도를 분리합니다.
  • 증거 보존 — 원인 추적 전 관측 데이터를 먼저 확보합니다.
  • 오버헤드(Overhead) 관리 — 추적 범위를 최소화해 왜곡을 줄입니다.
  • 사후 검증 — 수정 후 동일 조건에서 재발 여부를 확인합니다.

단계별 이해

  1. 재현 시나리오 정의
    입력 조건과 타이밍을 고정합니다.
  2. 관측 포인트 배치
    핵심 함수/이벤트만 선별 추적합니다.
  3. 원인 축소
    가설을 하나씩 배제하며 범위를 줄입니다.
  4. 수정 검증
    회귀 테스트와 운영 지표를 함께 확인합니다.
관련 표준: GNU Toolchain Documentation, LLVM Documentation — 커널 개발에 사용되는 컴파일러 및 도구 체인입니다. 종합 목록은 참고자료 — 표준 & 규격 섹션을 참고하세요.

개발 도구 선택 매트릭스

커널 개발 단계와 목적에 따라 필요한 도구가 다릅니다. 아래 매트릭스는 각 도구의 용도와 우선순위(Priority)를 정리합니다.

도구 주요 용도 필수 여부 사용 시점 대상 사용자
GCC 커널 컴파일 ★★★ 필수 빌드 모든 개발자
checkpatch.pl 코딩 스타일 검사 ★★★ 필수 커밋 전 패치 제출자
sparse 정적 분석 (NULL 체크, 락 검증) ★★☆ 권장 빌드 시 모든 개발자
coccinelle 패턴 기반 코드 변환 ★★☆ 권장 대규모 리팩토링 서브시스템 메인테이너
git format-patch 패치 생성 ★★★ 필수 패치 제출 패치 제출자
b4 패치 시리즈 다운로드/적용 ★★☆ 권장 패치 리뷰 메인테이너
QEMU 가상머신 테스트 ★★☆ 권장 테스트 모든 개발자
Clang 대체 컴파일러 ★☆☆ 선택 빌드 검증 서브시스템 메인테이너
pahole 구조체(Struct) 레이아웃 분석 ★☆☆ 선택 최적화 성능 튜닝 전문가
KUnit/kselftest 단위 테스트 ★★☆ 권장 개발 중 새 기능 개발자
💡

도구 우선순위 가이드:

  • 첫 패치 제출자: GCC + checkpatch.pl + git format-patch (최소 필수)
  • 정기 기여자: + sparse + QEMU + KUnit (품질 향상)
  • 메인테이너: + coccinelle + b4 + Clang (대규모 관리)
  • 성능 전문가: + pahole + perf + ftrace (상세 분석)

개발 환경 구축

커널 개발에 필요한 최소 패키지:

# Debian/Ubuntu
sudo apt install build-essential bc bison flex libelf-dev \
    libssl-dev libncurses-dev dwarves python3 git

# Fedora/RHEL
sudo dnf install gcc make bc bison flex elfutils-libelf-devel \
    openssl-devel ncurses-devel dwarves python3 git

# 커널 소스 가져오기
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout $(git tag -l 'v*' | sort -V | tail -n1)  # 최신 릴리스 태그 체크아웃

GCC (GNU Compiler Collection)

커널은 릴리스마다 최소 GCC 버전 요구사항이 다릅니다. 빌드 전 scripts/min-tool-version.sh를 확인하고, 실무적으로는 GCC 8+를 권장합니다.

# 커널 빌드에서 사용되는 주요 GCC 옵션
-Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs
-fno-strict-aliasing -fno-common
-fno-delete-null-pointer-checks
-O2                                # 최적화 레벨
-fstack-protector-strong           # 스택 보호
-mgeneral-regs-only                # ARM64: FP/SIMD 레지스터 사용 금지
-mindirect-branch=thunk-extern     # Spectre 완화

# GCC 플러그인 (CONFIG_GCC_PLUGINS=y)
-fplugin=randomize_layout          # 구조체 랜덤화 (RANDSTRUCT)
-fplugin=stackleak_plugin          # 스택 리크 방지
-fplugin=latent_entropy             # 잠재적 엔트로피 수집

Clang/LLVM

ClangBuiltLinux 프로젝트 덕분에 Clang으로도 커널을 완전히 빌드할 수 있습니다:

# Clang으로 커널 빌드
make CC=clang LLVM=1 defconfig
make CC=clang LLVM=1 -j$(nproc)

# Clang 전용 기능
CONFIG_CC_IS_CLANG=y
CONFIG_CFI_CLANG=y          # Control-Flow Integrity
CONFIG_LTO_CLANG_THIN=y     # Link-Time Optimization (Thin LTO)
CONFIG_SHADOW_CALL_STACK=y  # 섀도 콜 스택 (ARM64)
특성GCCClang
빌드 속도보통약간 빠름
진단 메시지보통우수 (색상, 제안)
LTO제한적Thin LTO 지원
CFI미지원지원
플러그인GCC 플러그인 다수LLVM pass
아키텍처모든 아키텍처x86, ARM, ARM64 위주

코드 분석 도구

sparse

Linus Torvalds가 작성한 정적 분석 도구. 주소 공간(Address Space) 혼합(__user, __kernel), endian 오류, lock 문제를 검출합니다:

# sparse로 커널 빌드 검사
make C=1    # 변경된 파일만 검사
make C=2    # 모든 파일 검사

# 특정 파일만 검사
make C=1 drivers/net/ethernet/intel/e1000e/
/* sparse 어노테이션 */
void my_ioctl(void __user *ubuf, void __iomem *mmio)
{
    /* sparse 경고: __user 포인터 역참조는 copy_from_user 사용 필요 */
    /* sparse 경고: __iomem 포인터는 readl/writel 사용 필요 */
}

Coccinelle

시맨틱 패치(Semantic Patch) 도구. 코드 변환 패턴을 SmPL 언어로 정의합니다:

# Coccinelle 시맨틱 패치 실행
make coccicheck MODE=report  # 보고만
make coccicheck MODE=patch   # 패치 적용

# 특정 스크립트만 실행
make coccicheck COCCI=scripts/coccinelle/api/kfree.cocci

checkpatch.pl

커널 코딩 스타일 검사 도구. 패치 제출 전 반드시 실행해야 합니다:

# 패치 파일 검사
scripts/checkpatch.pl 0001-my-patch.patch

# 파일 직접 검사
scripts/checkpatch.pl --file drivers/mydriver/myfile.c

# 엄격 모드
scripts/checkpatch.pl --strict 0001-my-patch.patch

# 주요 경고 유형
# WARNING: line length exceeds 100 columns
# WARNING: Missing a blank line after declarations
# ERROR: trailing whitespace
# ERROR: code indent should use tabs where possible
# CHECK: Alignment should match open parenthesis
💡

checkpatch.pl의 경고/오류 유형별 대응법과 코딩 스타일 검증 워크플로는 커널 코딩 스타일 문서에서 상세히 다룹니다.

커널 코딩 스타일 (Kernel Coding Style)

리눅스 커널은 Documentation/process/coding-style.rst에 정의된 고유한 코딩 스타일을 따릅니다. 이 스타일은 Linus Torvalds가 제정하였으며, 모든 패치 제출 시 반드시 준수해야 합니다. 핵심 규칙을 아래에 요약하며, 각 규칙의 상세 설명과 실전 예제는 커널 코딩 스타일 전용 문서를 참고하세요.

코딩 스타일 빠른 참조

항목 규칙 예시
들여쓰기 탭 8칸 (스페이스 금지) if (x) {⟨TAB⟩statement;
줄 길이 80열 권장, 100열 최대 긴 줄은 여는 괄호 뒤에서 나눔
중괄호 K&R 스타일 (함수만 다음 줄) if (x) { vs int f()\n{
함수명 소문자_언더스코어 my_function()
변수명 짧고 명확 (단일 문자도 OK) i, tmp, ret (지역 변수)
매크로(Macro) 대문자_언더스코어 #define MAX_SIZE 100
주석 /* C89 스타일 */ // C99 한 줄 주석은 일부 허용
goto 에러 처리에 적극 사용 goto err_free; (정리 레이블)
함수 인자 출력 매개변수는 포인터로 int get_value(int *out)
반환 값 성공 0, 실패 -errno return -EINVAL;
💡

들여쓰기, 중괄호, 네이밍, typedef, 함수 규칙, goto 패턴, 매크로, 반환값, 공백, kernel-doc 주석, 메모리 할당, printk 로깅, 조건부 컴파일, 에디터 설정 등 각 규칙의 상세 설명과 코드 예제는 커널 코딩 스타일 전용 문서를 참고하세요.

pahole과 BTF

pahole은 구조체의 메모리 레이아웃을 분석합니다. hole(패딩(Padding))을 찾아 구조체를 최적화할 수 있습니다:

# 구조체 레이아웃 분석
pahole -C task_struct vmlinux | head -50
# struct task_struct {
#     struct thread_info         thread_info;  /*     0    24 */
#     unsigned int               __state;      /*    24     4 */
#     /* ... */
#     /* size: 9792, cachelines: 153, members: 259 */
#     /* sum members: 9600, holes: 14, sum holes: 192 */

# BTF 생성 (BPF Type Format)
CONFIG_DEBUG_INFO_BTF=y
# pahole --btf_encode_detached btf_vmlinux vmlinux

Git 워크플로

# 커널 패치 생성
git format-patch -1 HEAD                      # 마지막 커밋을 패치로
git format-patch -3 --cover-letter            # 3개 커밋 + 커버 레터

# 패치 전송
git send-email --to=subsystem@vger.kernel.org \
    --cc=maintainer@kernel.org \
    0001-my-patch.patch

# 메인테이너 찾기
scripts/get_maintainer.pl 0001-my-patch.patch

# git bisect로 버그 커밋 찾기
git bisect start
git bisect bad                  # 현재 커밋은 버그 있음
git bisect good v6.5            # v6.5는 정상
# ... 커널 빌드 & 테스트 반복 ...
git bisect good                 # 또는 git bisect bad
git bisect reset                # 완료 후 리셋

# b4 도구 (메일링 리스트 패치 관리)
b4 am 20231115120000.12345-1-developer@kernel.org  # 패치 시리즈 적용
b4 shazam                                           # 현재 lore URL의 패치 적용

패치 제출 체크리스트

커널 패치를 메인라인에 제출하기 전 반드시 확인해야 할 필수 항목입니다. 이 체크리스트를 따르지 않으면 메인테이너에게 거부되거나 무시됩니다.

단계 체크 항목 명령어/도구 통과 기준
1. 코드 품질 ☐ checkpatch.pl 실행 scripts/checkpatch.pl --strict *.patch ERROR 0개, WARNING 최소화
☐ sparse 검사 make C=2 경고 없음 (수정 분야만)
☐ 컴파일 성공 make allmodconfig && make -j$(nproc) 빌드 에러 0개
2. 테스트 ☐ 기능 테스트 QEMU 또는 실제 하드웨어 변경 사항 정상 동작
☐ 회귀 테스트 KUnit, kselftest 기존 테스트 모두 통과
☐ GCC/Clang 모두 빌드 make CC=clang LLVM=1 양쪽 컴파일러 성공
3. 커밋 메시지 ☐ 서브시스템 접두사 git log --oneline 참조 subsys: Description 형식
☐ 본문 작성 (why) 72열 줄바꿈 변경 이유 명확 설명
☐ Signed-off-by git commit -s 본인 실명 + 이메일
☐ Fixes/Cc 태그 (버그 수정 시) Fixes: 12-char-SHA stable 백포트 대상 명시
4. 대상 확인 ☐ 메인테이너 확인 scripts/get_maintainer.pl *.patch To/Cc 리스트 확보
☐ 메일링리스트 구독 linux-kernel@vger.kernel.org 서브시스템 리스트 포함
☐ lore 검색 (중복 확인) lore.kernel.org 검색 동일 패치 없음 확인
5. 포맷 검증 ☐ 패치 시리즈 번호 git format-patch -3 -v2 [PATCH v2 1/3] 형식
☐ 커버 레터 (3개+ 패치) --cover-letter 시리즈 전체 설명
☐ In-Reply-To 설정 (v2+) --in-reply-to=<msg-id> 이전 버전 쓰레드 연결
6. 제출 ☐ git send-email 설정 ~/.gitconfig sendmail 설정 SMTP 정상 동작
☐ 자기 앞 테스트 발송 본인 이메일로 먼저 발송 포맷 확인 후 본 발송
⚠️

자주 거부되는 이유:

  1. checkpatch.pl ERROR 미수정
  2. Signed-off-by 누락 (DCO 위반)
  3. 커밋 메시지에 "why" 설명 없음
  4. 잘못된 메인테이너에게 발송
  5. HTML 메일 발송 (plain text 필수)
  6. 첨부 파일로 패치 발송 (인라인 필수)
  7. 여러 무관한 변경을 한 패치로 뭉침
💡

첫 패치 제출 팁:

  • 작게 시작: 오타 수정, checkpatch 정리 등 간단한 패치로 프로세스(Process) 익히기
  • Documentation/ 먼저: 문서 개선은 리뷰 부담이 적고 승인율 높음
  • staging/ 드라이버: drivers/staging은 품질 기준이 낮아 입문용으로 적합
  • 리뷰 반영: 메인테이너 피드백은 24시간 내 응답, 수정 후 v2 발송
  • patience: 답변까지 1~2주 소요 가능, 2주 후 polite ping 허용

QEMU 테스트 환경

# 최소 커널 + initramfs로 QEMU 부팅
make x86_64_defconfig
make -j$(nproc)

# 최소 initramfs 생성
mkdir -p rootfs/bin
cp /path/to/busybox rootfs/bin/busybox
cd rootfs/bin && ln -s busybox sh && cd ../..

cat > rootfs/init << 'EOF'
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t debugfs debugfs /sys/kernel/debug
echo "Boot OK"
exec /bin/sh
EOF
chmod +x rootfs/init
cd rootfs && find . | cpio -o -H newc | gzip > ../initramfs.gz && cd ..

# QEMU 실행
qemu-system-x86_64 \
    -kernel arch/x86/boot/bzImage \
    -initrd initramfs.gz \
    -append "console=ttyS0 nokaslr" \
    -nographic -m 1G -smp 4 \
    -enable-kvm

# 9p 파일시스템 공유 (호스트 디렉토리를 게스트에 마운트)
qemu-system-x86_64 ... \
    -fsdev local,id=shared,path=/path/to/share,security_model=none \
    -device virtio-9p-pci,fsdev=shared,mount_tag=hostshare
# 게스트에서: mount -t 9p hostshare /mnt

크로스 컴파일(Cross Compilation)

# ARM64 크로스 컴파일
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make defconfig
make -j$(nproc)

# RISC-V 크로스 컴파일
export ARCH=riscv
export CROSS_COMPILE=riscv64-linux-gnu-
make defconfig
make -j$(nproc)

# 크로스 컴파일 툴체인 설치
# Debian/Ubuntu:
sudo apt install gcc-aarch64-linux-gnu gcc-riscv64-linux-gnu
# Fedora:
sudo dnf install gcc-aarch64-linux-gnu gcc-riscv64-linux-gnu

IDE/에디터 설정

# compile_commands.json 생성 (clangd/ccls용)
scripts/clang-tools/gen_compile_commands.py

# 또는 bear 사용
bear -- make -j$(nproc)

# cscope/ctags 생성
make cscope tags

# VS Code 설정: .vscode/c_cpp_properties.json
# "compileCommands": "${workspaceFolder}/compile_commands.json"

# Vim + cscope
# :cscope add cscope.out
# :cs find g function_name    (정의 찾기)
# :cs find c function_name    (호출처 찾기)
# :cs find s symbol_name      (심볼 참조 찾기)

KUnit과 kselftest

# KUnit: 커널 단위 테스트 프레임워크
./tools/testing/kunit/kunit.py run --arch=x86_64

# 특정 테스트만 실행
./tools/testing/kunit/kunit.py run --kunitconfig=lib/kunit/.kunitconfig

# kselftest: 커널 셀프 테스트
make -C tools/testing/selftests run_tests
make -C tools/testing/selftests TARGETS=net run_tests  # 네트워크 테스트만

커널 문서화

# kernel-doc 형식의 함수 주석
# HTML 문서 빌드
make htmldocs
# 결과: Documentation/output/

# 특정 서브시스템 문서만
make SPHINXDIRS=driver-api htmldocs
/**
 * kmalloc - allocate kernel memory
 * @size: how many bytes of memory are required
 * @flags: GFP allocation flags
 *
 * kmalloc is the normal method of allocating memory
 * for objects smaller than page size in the kernel.
 *
 * Return: pointer to allocated memory, or NULL on failure
 */
void *kmalloc(size_t size, gfp_t flags);

개발 워크플로 다이어그램

커널 개발 워크플로 코드 수정 checkpatch sparse 빌드 & 테스트 QEMU 부팅 KUnit git format-patch git send-email 리뷰 피드백 반영 LKML / 서브시스템 메일링 리스트
코드 수정 → 검사 → 빌드/테스트 → QEMU → 패치 전송 → 리뷰 반영 사이클
💡

참고 자료: 커널 패치 제출 가이드, ClangBuiltLinux, Documentation/dev-tools/

커널 개발 도구 상세 실행 가이드

GCC 커널 빌드 주요 옵션

# 커널이 기본 사용하는 GCC 플래그 (top-level Makefile)
-Wall -Wundef -Werror=strict-prototypes -Werror=implicit-function-declaration
-Wno-trigraphs -fno-strict-aliasing -fno-common
-fno-delete-null-pointer-checks -fno-stack-protector
-Wdeclaration-after-statement -Wno-pointer-sign

# 아키텍처 의존 플래그 (x86_64)
-mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx
# ↑ 커널 코드에서 SIMD 레지스터 사용 금지 (kernel_fpu_begin 없이)
-mno-red-zone    # Red Zone 비활성화 (인터럽트 핸들러 안전성)
-mcmodel=kernel  # 커널 주소 공간 (상위 2GB) 코드 모델
-fno-pie         # PIE 비활성화 (KASLR은 별도 메커니즘)
-mstack-protector-guard=global  # Stack Canary

# 디버그 빌드
make KCFLAGS="-g -O0" menuconfig    # 최적화 제거 (디버깅 시)
make KCFLAGS="-fsanitize=undefined" # UBSAN (Undefined Behavior)

# 빌드 시간 최적화
make -j$(nproc)                     # 병렬 빌드 (CPU 코어 수)
make CC="ccache gcc" -j$(nproc)     # ccache로 재빌드 가속

GDB 커널 디버깅 상세

QEMU의 -s -S 옵션으로 GDB 디버그 포트를 열고, vmlinux 심볼 파일을 로드하여 커널을 소스 수준에서 디버깅할 수 있습니다. scripts/gdb/의 lx-dmesg, lx-ps 등 커널 전용 GDB 확장 명령을 활용하면 커널 내부 상태를 효과적으로 분석할 수 있습니다.

참고: QEMU+GDB 연결 설정, 브레이크포인트, 커널 모듈(Kernel Module) 디버깅, lx-* 명령 등 상세 내용은 GDB 커널 디버깅 전용 페이지(Page)를 참고하세요.

ftrace 상세 사용법

# ftrace 기본 설정 경로
FTRACE=/sys/kernel/debug/tracing

# 사용 가능한 트레이서 목록
cat $FTRACE/available_tracers
# nop function function_graph irqsoff preemptoff preemptirqsoff wakeup

# function 트레이서: 함수 호출 추적
echo function > $FTRACE/current_tracer
echo tcp_sendmsg > $FTRACE/set_ftrace_filter  # 특정 함수만
echo 1 > $FTRACE/tracing_on
cat $FTRACE/trace_pipe  # 실시간 출력

# function_graph 트레이서: 함수 호출 트리
echo function_graph > $FTRACE/current_tracer
echo vfs_write > $FTRACE/set_graph_function  # 진입점
echo 5 > $FTRACE/max_graph_depth             # 최대 깊이
cat $FTRACE/trace

# 이벤트 기반 트레이싱
echo 1 > $FTRACE/events/sched/sched_switch/enable   # 스케줄러 이벤트
echo 1 > $FTRACE/events/irq/irq_handler_entry/enable # IRQ 이벤트
echo 1 > $FTRACE/events/kmem/kmalloc/enable           # 메모리 할당

# 트리거: 특정 함수 호출 시 스택 트레이스
echo 'stacktrace' > $FTRACE/set_ftrace_filter
echo '__alloc_pages:stacktrace' >> $FTRACE/set_ftrace_filter

# 히스토그램 (5.x+)
echo 'hist:keys=common_pid:vals=hitcount' > \
    $FTRACE/events/sched/sched_switch/trigger

perf 상세 사용법

perf는 Linux 커널의 성능 카운터 서브시스템(perf_events)을 활용하는 프로파일링(Profiling) 도구입니다. CPU 사이클, 캐시(Cache) 미스, 브랜치 예측 실패 등의 하드웨어 카운터와 tracepoint 기반 소프트웨어 이벤트를 통합적으로 분석할 수 있으며, Flame Graph 생성, 스케줄러(Scheduler) 지연(Latency) 분석, 동적 프로브(Probe) 등 다양한 기능을 제공합니다.

참고: perf stat/record/report, Flame Graph, perf probe, perf sched, perf c2c 등 상세 사용법은 디버깅 — perf 전용 페이지를 참고하세요.

bpftrace 상세 사용법

# bpftrace: eBPF 기반 동적 트레이싱 (awk-like 문법)

# 시스템 콜 빈도 (5초간)
bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }' -d 5

# 프로세스별 read 크기 히스토그램
bpftrace -e 'tracepoint:syscalls:sys_exit_read /args->ret > 0/ {
    @bytes[comm] = hist(args->ret);
}'

# 디스크 I/O 지연 분석
bpftrace -e 'tracepoint:block:block_rq_issue {
    @start[args->dev, args->sector] = nsecs;
}
tracepoint:block:block_rq_complete /@start[args->dev, args->sector]/ {
    @usecs = hist((nsecs - @start[args->dev, args->sector]) / 1000);
    delete(@start[args->dev, args->sector]);
}'

# TCP retransmit 추적
bpftrace -e 'kprobe:tcp_retransmit_skb {
    @[kstack] = count();
}'

# 커널 함수 인자 접근
bpftrace -e 'kprobe:vfs_read {
    @bytes[comm] = hist(arg2);  /* arg2 = count */
}'

KASAN / KMSAN / UBSAN 상세

커널 새니타이저는 런타임 메모리 오류를 감지하는 강력한 디버깅 도구입니다. KASAN은 use-after-free, out-of-bounds 등을 감지하고(Generic/SW_TAGS/HW_TAGS 모드), KMSAN은 초기화되지 않은 메모리 사용을(Clang 전용), UBSAN은 정수 오버플로(Integer Overflow) 등 미정의 동작을 감지합니다. 프로덕션 환경에서는 KFENCE로 낮은 오버헤드의 확률적 감지가 가능합니다.

참고: KASAN/KMSAN/UBSAN/KFENCE 설정 방법과 사용 예제는 KASAN 메모리 새니타이저디버깅 전용 페이지를 참고하세요.

커널 빌드 도구

리눅스 커널의 빌드 시스템(Build System)은 GNU Make를 기반으로 하며, Kconfig로 설정을 관리하고 Kbuild로 실제 컴파일 규칙을 정의합니다. 이 세 가지 구성 요소가 유기적으로 결합하여 수천 개의 소스 파일을 효율적으로 관리합니다.

make 주요 타겟

커널 빌드에서 자주 사용하는 make 타겟을 목적별로 분류합니다.

카테고리타겟설명사용 예시
설정menuconfigncurses 기반 TUI 설정 메뉴make menuconfig
nconfig향상된 ncurses 설정 메뉴make nconfig
xconfigQt 기반 GUI 설정 메뉴make xconfig
olddefconfig기존 .config 유지, 새 옵션은 기본값make olddefconfig
빌드allvmlinux + 모듈 + dtbs 전체 빌드make -j$(nproc)
bzImage압축된 커널 이미지 (x86)make bzImage
modules모듈만 빌드make modules
modules_install모듈 설치make modules_install
설정 생성defconfig아키텍처 기본 설정make defconfig
allmodconfig가능한 모든 옵션을 모듈로make allmodconfig
tinyconfig최소 설정 (빠른 빌드 테스트)make tinyconfig
정리clean빌드 결과물 제거make clean
mrproperclean + .config 제거make mrproper
distcleanmrproper + 에디터 백업 제거make distclean
분석cscopecscope 인덱스 생성make cscope
tagsctags 인덱스 생성make tags
htmldocsHTML 문서 빌드make htmldocs

Kconfig 시스템

Kconfig는 커널 설정 옵션을 선언적으로 정의하는 언어입니다. 각 서브시스템의 Kconfig 파일에 설정 항목, 의존성, 도움말이 정의됩니다.

# drivers/net/ethernet/intel/Kconfig 예시
config E1000E
    tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet"
    depends on PCI
    select CRC32
    select PTP_1588_CLOCK
    help
      This driver supports Intel PRO/1000 PCI-Express ethernet adapters.

      To compile this driver as a module, choose M here.
      The module will be called e1000e.

# Kconfig 주요 키워드
# config    : 새 설정 항목 정의
# bool      : y/n 선택
# tristate  : y/m/n 선택 (모듈 가능)
# int       : 정수 값
# string    : 문자열 값
# depends on: 의존성 (조건 미충족 시 숨김)
# select    : 강제 활성화 (역방향 의존성)
# imply     : 약한 select (사용자 비활성화 가능)
# default   : 기본값
# menuconfig: 하위 메뉴를 포함하는 설정 항목
# choice    : 상호 배타적 선택 그룹
# .config 파일 조작 유틸리티
scripts/config --enable CONFIG_E1000E
scripts/config --disable CONFIG_E1000E
scripts/config --module CONFIG_E1000E
scripts/config --set-val CONFIG_LOG_BUF_SHIFT 18
scripts/config --set-str CONFIG_LOCALVERSION "-custom"

# 두 .config 파일 비교
scripts/diffconfig .config.old .config

# 설정 의존성 분석
make listnewconfig     # 새 .config에만 있는 옵션
make oldconfig         # 새 옵션마다 대화형 질문
make syncconfig        # 내부적으로 헤더 파일 동기화

Kbuild 시스템

Kbuild는 각 디렉토리의 Makefile에서 오브젝트 파일을 선언하는 방식으로 동작합니다. obj-y는 내장(Built-in), obj-m은 모듈로 빌드됩니다.

# drivers/net/ethernet/intel/e1000e/Makefile
obj-$(CONFIG_E1000E) += e1000e.o
e1000e-objs := netdev.o ethtool.o ich8lan.o 82571.o mac.o \
               nvm.o phy.o manage.o ptp.o

# Kbuild 변수 종류
obj-y          += foo.o        # 내장 컴파일
obj-m          += bar.o        # 모듈 컴파일
obj-$(CONFIG_X) += baz.o       # 설정에 따라 결정

# 추가 컴파일 플래그
ccflags-y      += -DDEBUG     # 디렉토리 전체에 적용
CFLAGS_foo.o   += -O0         # 특정 파일에만 적용

# 하위 디렉토리
obj-y          += subdirectory/
# Kbuild 빌드 과정 상세 보기
make V=1 drivers/net/ethernet/intel/e1000e/   # 실행 명령 표시
make V=2 drivers/net/ethernet/intel/e1000e/   # 왜 재빌드하는지 표시

# 특정 파일만 빌드
make drivers/net/ethernet/intel/e1000e/netdev.o

# 전처리(Preprocessing) 결과 확인
make drivers/net/ethernet/intel/e1000e/netdev.i

# 어셈블리 출력
make drivers/net/ethernet/intel/e1000e/netdev.s

# 빌드 시간 프로파일링
make -j$(nproc) 2>&1 | ts '[%H:%M:%.S]'  # moreutils의 ts 사용
Kbuild 빌드 시스템 흐름 Kconfig 파일 설정 선언 menuconfig 사용자 선택 .config 설정 결과 include/generated/ autoconf.h 생성 소스 파일 (.c) drivers/, kernel/ Kbuild Makefile obj-y, obj-m GCC / Clang 컴파일 오브젝트 (.o) built-in.a, .ko vmlinux.lds 링커 스크립트 링커 (ld) 최종 링크 vmlinux ELF 커널 이미지 bzImage / Image 압축 부팅 이미지
Kconfig → .config → Kbuild → 컴파일 → 링크 → 부팅 가능 이미지 생성 과정

빌드 가속: ccache와 distcc

# ccache: 컴파일 결과 캐싱으로 재빌드 속도 향상
sudo apt install ccache
make CC="ccache gcc" -j$(nproc)

# ccache 통계 확인
ccache -s
# Hits:           12345
# Misses:         678
# Hit ratio:      94.80%

# ccache 크기 설정 (기본 5GB)
ccache -M 20G

# distcc: 분산 컴파일 (네트워크의 여러 머신 활용)
sudo apt install distcc
export DISTCC_HOSTS="localhost worker1 worker2 worker3"
make CC="distcc gcc" -j$(($(nproc) * 4))

# ccache + distcc 결합
export CCACHE_PREFIX=distcc
make CC="ccache gcc" -j$(($(nproc) * 4))

소스 탐색 도구

수만 개의 파일로 구성된 리눅스 커널 소스를 효과적으로 탐색하려면 전용 인덱싱 도구가 필수입니다. 함수 정의(Definition), 호출 관계(Call Graph), 심볼 참조(Symbol Reference) 등을 빠르게 검색할 수 있습니다.

cscope

cscope는 대규모 C 코드베이스를 위한 대화형 소스 탐색 도구입니다. 커널은 make cscope 타겟을 내장하고 있어 인덱스 생성이 간편합니다.

# cscope 인덱스 생성 (커널 내장 타겟)
make cscope

# 수동 인덱스 생성 (세밀한 제어)
find . -name '*.c' -o -name '*.h' -o -name '*.S' > cscope.files
cscope -b -q -k         # -b: 빌드만, -q: 역방향 인덱스, -k: 커널 모드

# cscope 대화형 검색 (터미널)
cscope -d               # 인덱스 로드 후 검색 모드
# 0: 이 C 심볼을 찾습니다
# 1: 이 전역 정의를 찾습니다
# 2: 이 함수에 의해 호출되는 함수를 찾습니다
# 3: 이 함수를 호출하는 함수를 찾습니다
# 4: 이 텍스트 문자열을 찾습니다
# 6: 이 egrep 패턴을 찾습니다
# 7: 이 파일을 찾습니다
# 8: 이 파일을 #include 하는 파일을 찾습니다

# Vim에서 cscope 사용
# :cscope add cscope.out
# :cs find g schedule          → 함수 정의
# :cs find c schedule          → 호출하는 곳
# :cs find s task_struct       → 심볼 참조
# :cs find d sys_read          → 이 함수가 호출하는 함수
# :cs find t "EXPORT_SYMBOL"   → 텍스트 검색

ctags (Universal Ctags)

# ctags 인덱스 생성 (커널 내장 타겟)
make tags           # ctags 기반
make TAGS           # etags 기반 (Emacs용)

# Universal Ctags 수동 생성 (더 많은 옵션)
ctags -R --languages=C,C++ --exclude=.git \
    --fields=+lS --extras=+q \
    arch/x86 drivers/ fs/ include/ kernel/ mm/ net/

# Vim에서 ctags 사용
# :tag function_name            → 정의로 이동
# Ctrl-]                         → 커서 위치 태그로 이동
# Ctrl-t                         → 이전 위치로 복귀
# :tselect function_name        → 중복 태그 선택

GNU Global (gtags)

GNU Global은 cscope와 ctags의 기능을 결합한 소스 코드 태그 시스템입니다. 정의, 참조, 심볼을 모두 인덱싱하며 증분 업데이트(Incremental Update)를 지원합니다.

# GNU Global 설치 및 인덱스 생성
sudo apt install global
cd /path/to/linux
gtags                           # GPATH, GRTAGS, GTAGS 생성

# 증분 업데이트 (변경된 파일만 재인덱싱)
global -u

# 검색 명령
global -d schedule              # 정의 (definition)
global -r schedule              # 참조 (reference)
global -s EXPORT_SYMBOL         # 심볼 (symbol, grep)
global -g "spin_lock_irq"       # 패턴 검색 (grep)
global -x schedule              # 상세 정보 (정의 + 파일 + 줄번호)
global -P '*.c'                 # 파일 경로 검색

# htags: HTML 크로스 레퍼런스 생성
htags -Ffnsa                    # HTML/ 디렉토리에 결과 생성

Elixir Cross-Referencer

Bootlin에서 운영하는 Elixir Cross-Referencer는 웹 브라우저에서 커널 소스를 탐색할 수 있는 온라인 도구입니다. 설치 없이 사용할 수 있으며, 여러 커널 버전 간 코드 비교가 가능합니다.

도구유형장점단점추천 용도
cscope 로컬 CLI/TUI 호출 관계 추적, 커널 내장 지원 증분 업데이트 없음, C 전용 함수 호출 그래프 분석
ctags 로컬 CLI 빠른 태그 점프, 에디터 통합 참조 검색 미지원 빠른 정의 이동
GNU Global 로컬 CLI 증분 업데이트, 정의+참조 통합 초기 인덱싱 느림 대규모 분석 프로젝트
Elixir 웹 기반 설치 불필요, 버전 비교 오프라인 불가, 커스텀 코드 불가 빠른 참조, 코드 리뷰
clangd/ccls LSP 서버 IDE 통합, 의미 분석 compile_commands.json 필요 IDE 기반 개발

정적 분석 도구 상세

정적 분석(Static Analysis)은 코드를 실행하지 않고 소스 수준에서 결함을 탐지하는 기법입니다. 커널 개발에서는 주소 공간 혼동, 잠금 규약(Locking Protocol) 위반, API 오용 등을 컴파일 시점에 발견할 수 있습니다.

smatch

smatch는 커널 코드에 특화된 정적 분석 도구로, sparse보다 더 정교한 데이터 흐름(Data Flow) 분석을 수행합니다. 널 포인터 역참조(NULL Pointer Dereference), 범위 초과(Out-of-bounds), 잠금 불일치 등을 감지합니다.

# smatch 설치 (소스 빌드)
git clone https://repo.or.cz/smatch.git
cd smatch
make -j$(nproc)
sudo make install PREFIX=/usr/local

# smatch로 커널 검사
make CHECK="smatch -p=kernel" C=1
make CHECK="smatch -p=kernel" C=2  # 모든 파일

# 특정 검사만 실행
make CHECK="smatch -p=kernel --enable=check_locking" C=1

# smatch 주요 검사 항목
# - NULL 포인터 역참조 (check_deref, check_dereferences_param)
# - 범위 검사 (check_overflow, check_user_data)
# - 잠금 불일치 (check_locking)
# - use-after-free (check_free)
# - 초기화 안 된 변수 (check_uninitialized)
# - 에러 코드 반환 (check_return_efault, check_err_ptr)

Coccinelle

Coccinelle은 시맨틱 패치(Semantic Patch) 도구로, SmPL(Semantic Patch Language)을 사용하여 코드 변환 패턴을 정의합니다. 단순 정규식으로는 불가능한 구문 인식(Syntax-aware) 변환이 가능합니다.

// SmPL 예제: kzalloc 변환 (kmalloc + memset → kzalloc)
@@
expression x, size, flags;
statement S;
@@
- x = kmalloc(size, flags);
+ x = kzalloc(size, flags);
  if (x == NULL) S
- memset(x, 0, size);

// SmPL 예제: of_node_put() 누락 감지
@@
expression node;
@@
  node = of_find_compatible_node(...);
  ... when != of_node_put(node)
      when != return ...;
+ of_node_put(node);

// SmPL 예제: sizeof 타입 불일치 감지
@@
type T;
T *p;
@@
  p = kmalloc(
-   sizeof(T *)
+   sizeof(*p)
  , ...)
# Coccinelle 실행 방법
# 1) 커널 내장 coccicheck 타겟
make coccicheck MODE=report                    # 전체 검사 (보고만)
make coccicheck MODE=patch                     # 패치 자동 적용
make coccicheck MODE=context                   # 문맥 출력
make coccicheck MODE=org                       # org-mode 형식

# 2) 특정 스크립트만
make coccicheck COCCI=scripts/coccinelle/api/kfree.cocci MODE=report

# 3) 특정 디렉토리만
make coccicheck M=drivers/net/ MODE=report

# 4) 직접 실행
spatch --sp-file my_rule.cocci --dir drivers/net/ --include-headers

# 커널에 내장된 주요 Coccinelle 스크립트
ls scripts/coccinelle/
# api/           → API 변환 (kfree, alloc, ...)  
# free/          → 해제 관련 (double free, use-after-free)
# misc/          → 기타 패턴
# null/          → NULL 검사
# locks/         → 잠금 관련

Clang Static Analyzer

Clang 정적 분석기(Static Analyzer)는 경로 민감(Path-sensitive) 분석을 수행하여 데드 코드(Dead Code), 메모리 누수(Memory Leak), 초기화되지 않은 변수 사용 등을 탐지합니다.

# scan-build를 사용한 커널 분석
scan-build make CC=clang -j$(nproc)

# HTML 보고서 생성
scan-build -o /tmp/scan-report make CC=clang -j$(nproc)
# 결과: /tmp/scan-report/YYYY-MM-DD-HHMMSS/

# 특정 체커만 활성화
scan-build -enable-checker core.NullDereference \
           -enable-checker unix.Malloc \
           make CC=clang -j$(nproc)

# 주요 체커 목록
# core.NullDereference    : NULL 포인터 역참조
# core.DivideZero         : 0으로 나누기
# core.UndefinedBinaryOp  : 미정의 연산
# unix.Malloc             : 메모리 할당/해제 오류
# unix.MallocSizeof       : sizeof 불일치
# deadcode.DeadStores     : 사용되지 않는 대입
정적 분석 도구 적용 단계 소스 코드 drivers/*.c, kernel/*.c sparse (make C=1) 주소 공간, endian, 타입 검사 smatch 데이터 흐름, NULL 검사, 잠금 Coccinelle 패턴 매칭, API 오용, 변환 Clang Static Analyzer 경로 민감 분석, 메모리 누수 경고/오류 보고서 빌드 시 자동 출력 패치 제안 자동 코드 변환 코드 수정 결함 해결 → 커밋 분석 깊이: sparse (빠름, 가벼움) → smatch (중간) → Clang Analyzer (깊음, 느림) Coccinelle: 패턴 기반으로 독립적 — 리팩터링에 특히 유용
4가지 정적 분석 도구의 적용 단계와 출력물 비교
도구분석 유형커널 특화속도거짓 양성주요 검출 항목
sparse 타입 기반 매우 높음 빠름 낮음 __user/__iomem 혼동, endian, bitwise
smatch 데이터 흐름 높음 중간 중간 NULL 역참조, 범위 초과, 잠금 불일치
Coccinelle 패턴 매칭 높음 중간 낮음 API 오용, 코드 변환, 일관성
Clang Analyzer 경로 민감 낮음 느림 높음 메모리 누수, 데드 코드, use-after-free

동적 분석 도구

동적 분석(Dynamic Analysis)은 커널을 실행하면서 런타임(Runtime) 오류를 감지합니다. 새니타이저(Sanitizer)는 커널에 계측 코드(Instrumentation Code)를 삽입하여 메모리 접근, 동시성(Concurrency), 미정의 동작 등을 실시간으로 감시합니다.

KASAN (Kernel Address Sanitizer)

KASAN은 메모리 접근 오류를 런타임에 감지하는 가장 강력한 커널 도구입니다. 세 가지 모드를 지원합니다.

모드CONFIG 옵션컴파일러오버헤드사용 환경
Generic KASAN CONFIG_KASAN_GENERIC=y GCC/Clang 메모리 ~3x, CPU ~2x 개발/테스트
SW_TAGS KASAN CONFIG_KASAN_SW_TAGS=y Clang (ARM64) 메모리 ~1.5x, CPU ~1.2x ARM64 테스트
HW_TAGS KASAN CONFIG_KASAN_HW_TAGS=y GCC/Clang (ARM64 MTE) 메모리 ~1.05x, CPU ~1.05x 프로덕션 가능
# KASAN 활성화 커널 설정
scripts/config --enable CONFIG_KASAN
scripts/config --enable CONFIG_KASAN_GENERIC
scripts/config --enable CONFIG_KASAN_INLINE    # 더 빠른 검사 (바이너리 커짐)
scripts/config --enable CONFIG_KASAN_STACK     # 스택 변수 검사
make olddefconfig
make -j$(nproc)

# KASAN 보고 예시 (dmesg 출력)
# ==================================================================
# BUG: KASAN: slab-use-after-free in my_function+0x42/0x100
# Read of size 8 at addr ffff888012345678 by task test/1234
#
# Call Trace:
#  dump_stack_lvl+0x44/0x5c
#  print_report+0x17e/0x4b0
#  kasan_report+0xb4/0xf0
#  my_function+0x42/0x100
#
# Allocated by task 1234:
#  kmalloc_trace+0x26/0x60
#  my_alloc+0x20/0x50
#
# Freed by task 1234:
#  kfree+0x8e/0xb0
#  my_free+0x18/0x30
# ==================================================================

KMSAN (Kernel Memory Sanitizer)

# KMSAN: 초기화되지 않은 메모리 사용 감지 (Clang 전용)
scripts/config --enable CONFIG_KMSAN
make CC=clang LLVM=1 -j$(nproc)

# KMSAN 검출 예시
# ==================================================================
# BUG: KMSAN: uninit-value in my_function+0x42/0x100
# Uninit was created at:
#  kmalloc_trace+0x26/0x60
#  my_init+0x20/0x50
# ==================================================================

# 주의: KMSAN은 KASAN과 동시 사용 불가
# KMSAN은 현재 x86_64에서만 지원

KCSAN (Kernel Concurrency Sanitizer)

KCSAN은 데이터 경합(Data Race)을 감지하는 동시성 새니타이저입니다. 잠금 없이 공유 변수에 접근하는 코드를 찾아냅니다.

# KCSAN 활성화
scripts/config --enable CONFIG_KCSAN
scripts/config --enable CONFIG_KCSAN_REPORT_ONCE_IN_MS=0  # 모든 경합 보고
make -j$(nproc)

# KCSAN 보고 예시
# ==================================================================
# BUG: KCSAN: data-race in my_reader / my_writer
#
# write to 0xffff888012345678 of 4 bytes by task 5678:
#  my_writer+0x42/0x100
#
# read to 0xffff888012345678 of 4 bytes by task 1234:
#  my_reader+0x30/0x80
#
# value changed: 0x00000001 -> 0x00000002
# ==================================================================

# 의도적인 데이터 경합 표시 (false positive 방지)
# READ_ONCE(x), WRITE_ONCE(x, val) 사용
# data_race(expr) 래퍼 사용

UBSAN (Undefined Behavior Sanitizer)

# UBSAN 활성화 (GCC/Clang 모두 지원)
scripts/config --enable CONFIG_UBSAN
scripts/config --enable CONFIG_UBSAN_BOUNDS     # 배열 범위 검사
scripts/config --enable CONFIG_UBSAN_SHIFT      # 잘못된 시프트 감지
scripts/config --enable CONFIG_UBSAN_DIV_ZERO   # 0으로 나누기
scripts/config --enable CONFIG_UBSAN_UNREACHABLE # 도달 불가 코드
scripts/config --enable CONFIG_UBSAN_BOOL        # 잘못된 bool 값
scripts/config --enable CONFIG_UBSAN_ENUM        # 잘못된 enum 값
scripts/config --enable CONFIG_UBSAN_TRAP        # 위반 시 즉시 트랩 (디버깅용)
make -j$(nproc)

# UBSAN 검출 예시
# UBSAN: shift-out-of-bounds in drivers/foo/bar.c:123:4
# shift exponent 64 is too large for 32-bit type 'unsigned int'

lockdep (Lock Dependency Validator)

lockdep은 잠금 순서 위반과 잠재적 교착 상태(Deadlock)를 런타임에 감지하는 커널 내장 검증기입니다. 실제 교착이 발생하기 전에 잘못된 잠금 순서를 경고합니다.

# lockdep 활성화
scripts/config --enable CONFIG_LOCKDEP
scripts/config --enable CONFIG_PROVE_LOCKING    # 잠금 순서 증명
scripts/config --enable CONFIG_LOCK_STAT        # 잠금 경합 통계
scripts/config --enable CONFIG_DEBUG_LOCK_ALLOC # 잠금 할당 추적
make -j$(nproc)

# lockdep 보고 예시
# ============================================
# WARNING: possible circular locking dependency detected
# 6.x.0 #1 Not tainted
# -----------------------------------------------
# test/1234 is trying to acquire lock:
#  ffff888012345678 (&lock_A){+.+.}-{3:3}, at: func_b+0x20/0x50
#
# but task is already holding lock:
#  ffff888087654321 (&lock_B){+.+.}-{3:3}, at: func_a+0x18/0x40
#
# which lock already depends on the new lock.
# Possible unsafe locking scenario:
#        CPU0                    CPU1
#        ----                    ----
#   lock(&lock_A);               
#                               lock(&lock_B);
#                               lock(&lock_A);  ← 교착
#   lock(&lock_B);  ← 교착
# ============================================

# 잠금 통계 확인
cat /proc/lock_stat | head -50
새니타이저검출 대상메모리 오버헤드CPU 오버헤드컴파일러KASAN 동시 사용
KASAN (Generic) use-after-free, OOB, double-free ~3x ~2x GCC/Clang -
KMSAN 초기화 안 된 메모리 ~3x ~3x Clang only 불가
KCSAN 데이터 경합 낮음 낮음 GCC/Clang 가능
UBSAN 미정의 동작 (시프트, 오버플로) 낮음 낮음 GCC/Clang 가능
lockdep 교착, 잠금 순서 위반 ~1.5x 낮음 GCC/Clang 가능
KFENCE use-after-free, OOB (확률적) 매우 낮음 매우 낮음 GCC/Clang 불가

디버깅 도구

커널 디버깅은 사용자 공간 프로그램과 달리 특수한 환경이 필요합니다. GDB를 직접 연결하려면 QEMU나 KGDB를 사용해야 하고, 크래시(Crash) 후 분석은 kdump로 수집한 vmcore를 crash 유틸리티로 분석합니다.

GDB/KGDB 설정

# 1) QEMU + GDB (가장 일반적인 커널 디버깅 방법)
# 커널 빌드 (디버그 정보 포함)
scripts/config --enable CONFIG_DEBUG_INFO
scripts/config --enable CONFIG_DEBUG_INFO_DWARF5
scripts/config --enable CONFIG_GDB_SCRIPTS
scripts/config --disable CONFIG_RANDOMIZE_BASE     # KASLR 비활성화
make -j$(nproc)

# QEMU 실행 (GDB 대기 모드)
qemu-system-x86_64 \
    -kernel arch/x86/boot/bzImage \
    -initrd initramfs.gz \
    -append "console=ttyS0 nokaslr" \
    -nographic -m 2G -smp 2 \
    -s -S    # -s: GDB 포트 1234, -S: 시작 시 정지

# 다른 터미널에서 GDB 연결
gdb vmlinux
(gdb) target remote :1234
(gdb) lx-symbols                    # 모듈 심볼 로드
(gdb) break start_kernel
(gdb) continue
(gdb) lx-dmesg                      # dmesg 출력
(gdb) lx-ps                         # 프로세스 목록
(gdb) lx-lsmod                      # 모듈 목록
(gdb) lx-mounts                     # 마운트 목록
(gdb) p init_task.comm              # 구조체 필드 접근
(gdb) p/x init_task.mm->pgd         # 페이지 테이블

# 2) KGDB (실제 하드웨어에서 시리얼/네트워크 디버깅)
# 부트 파라미터:
# kgdboc=ttyS0,115200 kgdbwait

# 3) 커널 모듈 디버깅
# 모듈 로드 주소 확인 후 GDB에 추가
cat /sys/module/my_module/sections/.text
(gdb) add-symbol-file my_module.ko 0xffffffffc0000000

crash 유틸리티

crash는 실행 중인 커널이나 크래시 덤프(Crash Dump)를 분석하는 도구입니다. kdump/kexec으로 수집한 vmcore 파일을 사후에 분석할 수 있습니다.

# crash 설치
sudo apt install crash

# vmcore 분석
crash vmlinux /var/crash/vmcore

# crash 주요 명령
crash> bt             # 백트레이스 (현재 또는 크래시 태스크)
crash> bt -a          # 모든 CPU의 백트레이스
crash> bt 1234        # PID 1234의 백트레이스
crash> ps             # 프로세스 목록
crash> ps -m          # 메모리 사용량 포함
crash> task           # 현재 task_struct 출력
crash> struct task_struct ffff888012345678  # 특정 주소의 구조체
crash> kmem -s        # SLAB 캐시 정보
crash> kmem -i        # 메모리 사용 요약
crash> files 1234     # PID 1234의 열린 파일
crash> vm 1234        # PID 1234의 가상 메모리 영역
crash> log            # 커널 로그 (dmesg)
crash> dev            # 디바이스 목록
crash> net            # 네트워크 인터페이스
crash> mount          # 마운트 포인트
crash> mod            # 로드된 모듈
crash> rd -S ffff888012345678 32  # 메모리 읽기 (심볼 포함)
crash> dis -l func_name          # 함수 디스어셈블 (소스 줄 포함)

kdump/kexec

# kdump: 커널 패닉(Kernel Panic) 시 메모리 덤프 수집
# 1) kdump 설치 및 설정
sudo apt install kdump-tools kexec-tools

# 2) 크래시 커널용 메모리 예약 (GRUB)
# /etc/default/grub:
# GRUB_CMDLINE_LINUX="crashkernel=256M"
sudo update-grub

# 3) 커널 설정
scripts/config --enable CONFIG_KEXEC
scripts/config --enable CONFIG_CRASH_DUMP
scripts/config --enable CONFIG_PROC_VMCORE

# 4) 크래시 커널 로드 확인
cat /sys/kernel/kexec_crash_loaded   # 1이면 준비 완료

# 5) 수동 테스트 (주의: 시스템 크래시 유발)
echo c > /proc/sysrq-trigger         # 강제 크래시

# 6) 재부팅 후 vmcore 분석
ls /var/crash/                        # vmcore 파일 위치
crash vmlinux /var/crash/*/vmcore

dmesg와 printk

# dmesg: 커널 링 버퍼(Ring Buffer) 출력
dmesg                         # 전체 출력
dmesg -T                      # 사람 읽기 가능한 타임스탬프
dmesg -w                      # 실시간 모니터링 (follow)
dmesg -l err,warn              # 특정 레벨만
dmesg -k                      # 커널 메시지만
dmesg --clear                 # 버퍼 지우기

# printk 로그 레벨
# 0 = KERN_EMERG     (시스템 사용 불가)
# 1 = KERN_ALERT     (즉시 조치 필요)
# 2 = KERN_CRIT      (치명적 상태)
# 3 = KERN_ERR       (오류)
# 4 = KERN_WARNING   (경고)
# 5 = KERN_NOTICE    (정상이지만 중요)
# 6 = KERN_INFO      (정보)
# 7 = KERN_DEBUG     (디버그)

# 콘솔 로그 레벨 변경
echo 7 > /proc/sys/kernel/printk   # 디버그 메시지까지 출력

# 동적 디버그 (pr_debug/dev_dbg 활성화)
echo 'file drivers/net/*.c +p' > /sys/kernel/debug/dynamic_debug/control
echo 'module e1000e +p' > /sys/kernel/debug/dynamic_debug/control
echo 'func my_function +p' > /sys/kernel/debug/dynamic_debug/control
/* printk 사용 패턴 */
pr_info("device %s initialized\n", dev_name);        /* KERN_INFO */
pr_err("failed to allocate: %d\n", err);              /* KERN_ERR */
pr_warn("deprecated API used by %s\n", current->comm); /* KERN_WARNING */
pr_debug("entering %s\n", __func__);                  /* KERN_DEBUG (동적 디버그) */

/* 디바이스 드라이버용 (dev_info 등) */
dev_info(dev, "probe successful\n");
dev_err(dev, "firmware load failed: %d\n", ret);
dev_dbg(dev, "register 0x%04x = 0x%08x\n", reg, val);

/* 네트워크 드라이버용 */
netdev_info(netdev, "link up at %d Mbps\n", speed);
netdev_err(netdev, "TX timeout\n");

프로파일링 도구

커널 성능 분석에는 perf, ftrace, BPF 세 가지 주요 프레임워크가 사용됩니다. 각 도구는 서로 다른 관점에서 커널 동작을 분석하며, 상호 보완적으로 활용합니다.

perf

# perf stat: 하드웨어 카운터 기반 통계
perf stat -e cycles,instructions,cache-misses,branches,branch-misses \
    make -j$(nproc)

# perf record + report: 샘플링 기반 프로파일링
perf record -g -a -- sleep 10    # 10초 시스템 전체 샘플링
perf report --stdio              # 텍스트 보고서
perf report                      # TUI 보고서

# 커널 함수 프로파일링 (root 필요)
perf record -g -a -e cycles:k -- sleep 10  # 커널 모드만

# Flame Graph 생성
perf record -g -a -- sleep 30
perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg

# perf probe: 동적 트레이스포인트
perf probe -a 'vfs_read file->f_path.dentry->d_name.name:string'
perf record -e probe:vfs_read -a -- sleep 5
perf probe -d vfs_read          # 삭제

# perf sched: 스케줄러 분석
perf sched record -- sleep 10
perf sched latency              # 스케줄링 지연
perf sched map                  # CPU별 실행 맵

# perf c2c: 캐시 라인 경합 분석
perf c2c record -a -- sleep 10
perf c2c report --stdio

ftrace

# trace-cmd: ftrace의 사용자 친화적 프론트엔드
sudo apt install trace-cmd

# 기록 + 보고
trace-cmd record -p function_graph -g vfs_write sleep 5
trace-cmd report | head -100

# 특정 이벤트만 기록
trace-cmd record -e sched:sched_switch -e irq:irq_handler_entry sleep 10

# KernelShark: ftrace GUI 분석 도구
sudo apt install kernelshark
kernelshark trace.dat

# ftrace 인스턴스 (독립적 트레이싱 세션)
mkdir /sys/kernel/debug/tracing/instances/my_trace
echo function > /sys/kernel/debug/tracing/instances/my_trace/current_tracer
echo vfs_read > /sys/kernel/debug/tracing/instances/my_trace/set_ftrace_filter
echo 1 > /sys/kernel/debug/tracing/instances/my_trace/tracing_on

# 스냅샷 (현재 트레이스 버퍼 복사)
echo 1 > /sys/kernel/debug/tracing/snapshot
cat /sys/kernel/debug/tracing/snapshot

BPF/bpftool

BPF(Berkeley Packet Filter)는 커널 내에서 안전하게 실행되는 프로그램을 통해 관측성(Observability)을 제공합니다. perf나 ftrace보다 유연한 데이터 수집과 집계가 가능합니다. 상세한 내용은 BPF/XDP 전용 페이지를 참고하세요.

# bpftool: BPF 프로그램 및 맵 관리
bpftool prog list                # 로드된 BPF 프로그램 목록
bpftool map list                 # BPF 맵 목록
bpftool prog show id 123         # 특정 프로그램 상세 정보
bpftool map dump id 456          # 맵 내용 출력
bpftool btf dump file vmlinux    # BTF 타입 정보 출력

# BCC tools: 사전 빌드된 BPF 도구 모음
sudo apt install bpfcc-tools
execsnoop-bpfcc           # 프로세스 실행 추적
opensnoop-bpfcc           # 파일 오픈 추적
biolatency-bpfcc          # 블록 I/O 지연 히스토그램
tcplife-bpfcc             # TCP 연결 수명
runqlat-bpfcc             # 스케줄러 런큐 지연
funccount-bpfcc 'vfs_*'   # VFS 함수 호출 횟수
커널 프로파일링/트레이싱 도구 계층 사용자 공간 perf stat/record/report trace-cmd ftrace 프론트엔드 bpftrace eBPF 스크립팅 BCC tools 사전 빌드 도구 KernelShark GUI 분석 Flame Graph 시각화 커널 인터페이스 perf_events 서브시스템 HW/SW 카운터 ftrace 프레임워크 tracefs, 이벤트 BPF 가상 머신 JIT 컴파일, 검증기 kprobes / uprobes 동적 계측 커널 메커니즘 PMU (HW 카운터) cycles, cache-miss tracepoints 정적 계측 포인트 fentry/fexit 함수 진입/종료 kretprobes 함수 반환 가로채기 ring buffer per-CPU 이벤트 버퍼 perf_events, ftrace, BPF는 모두 tracepoints와 kprobes를 공유하며 상호 보완적으로 사용됩니다 프로덕션: perf stat/BCC | 개발: ftrace/bpftrace | 분석: perf record + Flame Graph
사용자 공간 도구 → 커널 인터페이스 → 하드웨어/소프트웨어 메커니즘의 계층 구조

코드 포맷팅 및 검사

커널 코드의 일관성을 유지하기 위해 자동화된 검사 도구들을 활용합니다. 패치 제출 전 반드시 이 도구들을 실행하여 코딩 스타일 위반을 사전에 수정해야 합니다.

checkpatch.pl

# checkpatch.pl 기본 사용법
scripts/checkpatch.pl 0001-my-patch.patch              # 패치 파일 검사
scripts/checkpatch.pl --file drivers/mydriver/myfile.c  # 파일 직접 검사
scripts/checkpatch.pl --strict 0001-my-patch.patch      # 엄격 모드
scripts/checkpatch.pl --terse 0001-my-patch.patch       # 간결 출력

# git hook으로 자동 검사
cat > .git/hooks/pre-commit << 'HOOK'
#!/bin/bash
git diff --cached --diff-filter=ACM | scripts/checkpatch.pl --no-signoff -
HOOK
chmod +x .git/hooks/pre-commit

# 특정 검사 무시
scripts/checkpatch.pl --ignore LONG_LINE,SPLIT_STRING 0001-my-patch.patch

# checkpatch 주요 메시지 유형
# ERROR:   반드시 수정 (패치 거부 사유)
# WARNING: 수정 권장 (리뷰어가 지적할 수 있음)
# CHECK:   선택적 (--strict 모드에서만 표시)

# 자주 발생하는 ERROR
# ERROR: trailing whitespace         → 줄 끝 공백 제거
# ERROR: code indent should use tabs → 스페이스 → 탭 변환
# ERROR: switch and case at same indent → case 들여쓰기
# ERROR: do not use C99 // comments  → /* */ 사용

# 자주 발생하는 WARNING
# WARNING: line length exceeds 80 columns     → 줄 길이 조절
# WARNING: Missing blank line after declaration → 빈 줄 추가
# WARNING: braces {} are not necessary for single statement → 불필요한 중괄호

clang-format

# 커널은 .clang-format 파일을 포함하고 있음
# 주의: clang-format은 보조 도구이며, checkpatch.pl이 최종 기준

# 파일 포맷팅 (변경 사항 출력만)
clang-format --style=file -n drivers/mydriver/myfile.c

# 파일 포맷팅 (직접 수정)
clang-format --style=file -i drivers/mydriver/myfile.c

# git diff와 결합 (변경된 줄만 포맷)
git diff -U0 HEAD~1 | clang-format-diff -p1 -style=file

# VS Code에서 설정
# settings.json:
# "C_Cpp.clang_format_style": "file"
# "editor.formatOnSave": true

테스트 프레임워크

커널 코드의 품질을 보장하기 위해 다양한 수준의 테스트 프레임워크가 존재합니다. 단위 테스트(Unit Test)부터 시스템 수준 퍼징(Fuzzing)까지, 각 프레임워크는 서로 다른 결함 유형을 대상으로 합니다.

KUnit 상세

KUnit은 커널 내장 단위 테스트 프레임워크입니다. 커널 함수를 격리된 환경에서 빠르게 테스트할 수 있으며, UML(User Mode Linux) 기반으로 실행하면 수 초 만에 결과를 확인할 수 있습니다.

# KUnit 기본 실행 (UML 기반 — 가장 빠름)
./tools/testing/kunit/kunit.py run

# 특정 테스트 스위트만 실행
./tools/testing/kunit/kunit.py run --filter "kunit_test*"

# 특정 .kunitconfig로 실행
./tools/testing/kunit/kunit.py run \
    --kunitconfig=drivers/base/.kunitconfig

# QEMU 기반 실행 (실제 아키텍처 테스트)
./tools/testing/kunit/kunit.py run --arch=x86_64 --qemu_config=...

# 결과 형식 지정
./tools/testing/kunit/kunit.py run --json     # JSON 출력
./tools/testing/kunit/kunit.py run --raw_output # KTAP 원본 출력

# KUnit 디버깅
./tools/testing/kunit/kunit.py run --make_options=LLVM=1  # Clang으로 빌드
./tools/testing/kunit/kunit.py run --alltests              # 모든 테스트
/* KUnit 테스트 작성 예시 */
#include <kunit/test.h>

static void example_add_test(struct kunit *test)
{
    /* 단언(Assertion) */
    KUNIT_EXPECT_EQ(test, 1 + 1, 2);
    KUNIT_EXPECT_NE(test, 1 + 1, 3);
    KUNIT_EXPECT_TRUE(test, 1 < 2);
    KUNIT_EXPECT_NOT_NULL(test, kmalloc(64, GFP_KERNEL));
}

static void example_alloc_test(struct kunit *test)
{
    struct my_struct *obj;

    /* KUnit 관리 리소스 (테스트 종료 시 자동 해제) */
    obj = kunit_kzalloc(test, sizeof(*obj), GFP_KERNEL);
    KUNIT_ASSERT_NOT_NULL(test, obj);  /* ASSERT: 실패 시 테스트 중단 */

    obj->value = 42;
    KUNIT_EXPECT_EQ(test, obj->value, 42);
    /* kfree 불필요 — kunit이 자동 정리 */
}

static struct kunit_case example_test_cases[] = {
    KUNIT_CASE(example_add_test),
    KUNIT_CASE(example_alloc_test),
    {}
};

static struct kunit_suite example_test_suite = {
    .name = "example",
    .test_cases = example_test_cases,
};

kunit_test_suite(example_test_suite);

kselftest 상세

# kselftest: 커널 기능 회귀 테스트 (사용자 공간에서 실행)

# 전체 테스트 실행
make -C tools/testing/selftests run_tests

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

# 빌드만 (설치 후 실행)
make -C tools/testing/selftests INSTALL_PATH=/tmp/kselftest install
/tmp/kselftest/run_kselftest.sh

# 개별 테스트 실행
cd tools/testing/selftests/net
make
./reuseport_bpf

# 주요 테스트 카테고리
# bpf/          : eBPF 프로그램 테스트
# mm/           : 메모리 관리 (mmap, hugepage, ...)
# net/          : 네트워크 스택
# ftrace/       : 트레이싱 기능
# cgroup/       : 제어 그룹
# filesystems/  : 파일시스템
# seccomp/      : 시스템 콜 필터링
# kvm/          : 가상화

LTP (Linux Test Project)

# LTP: 포괄적인 리눅스 커널 테스트 스위트
git clone https://github.com/linux-test-project/ltp.git
cd ltp
make autotools
./configure
make -j$(nproc)
sudo make install

# 전체 테스트 실행 (시간 오래 걸림)
cd /opt/ltp
sudo ./runltp

# 특정 테스트 그룹만
sudo ./runltp -f syscalls       # 시스템 콜 테스트
sudo ./runltp -f mm             # 메모리 관리 테스트
sudo ./runltp -f io             # I/O 테스트
sudo ./runltp -f net.tcp_cmds   # 네트워크 TCP 테스트

# 개별 테스트 실행
sudo ./testcases/bin/mmap01
sudo ./testcases/bin/fork01

syzkaller (커널 퍼저)

syzkaller는 Google이 개발한 커널 퍼징(Fuzzing) 도구로, 시스템 콜을 무작위 조합하여 커널 버그를 자동으로 발견합니다. syzbot은 syzkaller의 자동화된 CI 시스템으로, 매일 수천 개의 크래시를 자동 보고합니다.

# syzkaller 설치 (Go 필요)
git clone https://github.com/google/syzkaller.git
cd syzkaller
make

# 커널 설정 (syzkaller용)
# KASAN, KCSAN, lockdep 등 새니타이저 활성화 권장
scripts/config --enable CONFIG_KASAN
scripts/config --enable CONFIG_KCSAN
scripts/config --enable CONFIG_LOCKDEP
scripts/config --enable CONFIG_KCOV              # 커버리지 수집 (syzkaller 필수)
scripts/config --enable CONFIG_DEBUG_INFO
scripts/config --enable CONFIG_CONFIGFS_FS
scripts/config --enable CONFIG_SECURITYFS

# syzkaller 설정 (my.cfg)
# {
#     "target": "linux/amd64",
#     "http": "127.0.0.1:56741",
#     "workdir": "/tmp/syzkaller",
#     "kernel_obj": "/path/to/linux",
#     "image": "/path/to/bullseye.img",
#     "syzkaller": "/path/to/syzkaller",
#     "procs": 8,
#     "type": "qemu",
#     "vm": {
#         "count": 4,
#         "kernel": "/path/to/bzImage",
#         "cpu": 2,
#         "mem": 2048
#     }
# }

# 실행
./bin/syz-manager -config my.cfg

# 웹 대시보드: http://127.0.0.1:56741
# syzbot 자동 보고: https://syzkaller.appspot.com
프레임워크테스트 유형실행 환경속도주요 대상
KUnit 단위 테스트 UML / QEMU 매우 빠름 (수 초) 내부 API, 자료구조
kselftest 기능 테스트 실제 커널 (사용자 공간) 보통 (수 분) syscall, ABI 호환성
LTP 적합성 테스트 실제 커널 느림 (수 시간) POSIX 호환, 스트레스
syzkaller 퍼징 QEMU VM (다수) 연속 실행 미지의 버그 자동 발견
xfstests 파일시스템 테스트 실제 커널 느림 ext4, xfs, btrfs 등

버전 관리: Git 워크플로 상세

리눅스 커널은 세계 최대 규모의 Git 저장소 중 하나이며, 고유한 패치 기반 워크플로를 사용합니다. Pull Request 대신 메일링 리스트를 통한 패치 교환이 표준이며, 이를 위한 전용 도구들이 존재합니다.

git-send-email 설정

# git send-email 설치
sudo apt install git-email

# ~/.gitconfig 설정 예시 (Gmail SMTP)
git config --global sendemail.smtpserver smtp.gmail.com
git config --global sendemail.smtpserverport 587
git config --global sendemail.smtpencryption tls
git config --global sendemail.smtpuser your-email@gmail.com
# 앱 비밀번호 사용 (2FA 활성화 시):
git config --global sendemail.smtppass "xxxx-xxxx-xxxx-xxxx"

# 패치 생성 및 전송 전체 흐름
# 1) 작업 브랜치 생성
git checkout -b fix-null-deref origin/master

# 2) 코드 수정 및 커밋
git add -p                                       # 변경 내용 검토 후 스테이징
git commit -s                                    # -s: Signed-off-by 자동 추가

# 3) 커밋 메시지 형식
# subsystem: fix null pointer dereference in foo()
#
# When bar() returns NULL, we must check the return value
# before dereferencing. Otherwise, a null pointer exception
# can occur during probe.
#
# Fixes: a1b2c3d4e5f6 ("subsystem: add bar() support")
# Cc: stable@vger.kernel.org
# Signed-off-by: Your Name <your@email.com>

# 4) 패치 파일 생성
git format-patch -1 -v1 --subject-prefix="PATCH" HEAD

# 5) checkpatch 검사
scripts/checkpatch.pl v1-0001-*.patch

# 6) 메인테이너 확인
scripts/get_maintainer.pl v1-0001-*.patch

# 7) 자기 앞 테스트 발송
git send-email --to=your@email.com v1-0001-*.patch

# 8) 본 발송
git send-email \
    --to=subsystem@vger.kernel.org \
    --cc=maintainer1@kernel.org \
    --cc=maintainer2@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    v1-0001-*.patch

b4 도구

b4은 kernel.org에서 개발한 패치 시리즈 관리 도구입니다. lore.kernel.org에서 패치를 가져오고, 리뷰 태그를 수집하며, 패치를 재전송하는 작업을 자동화합니다.

# b4 설치
pip install b4

# 패치 시리즈 가져와 적용 (Message-ID 사용)
b4 am 20231115120000.12345-1-developer@kernel.org

# lore URL에서 패치 적용
b4 shazam https://lore.kernel.org/linux-kernel/20231115120000.12345-1-developer@kernel.org

# 패치 시리즈 정보 확인
b4 mbox 20231115120000.12345-1-developer@kernel.org

# b4 기반 패치 워크플로 (최신 방법)
# 1) 작업 준비
b4 prep --fork-point origin/master --set-prefix "PATCH"

# 2) 커밋 작성 (일반 git 작업)
git add -p && git commit -s

# 3) 커버 레터 편집
b4 prep --edit-cover

# 4) 패치 전송
b4 send

# 5) v2 전송 (리뷰 반영 후)
b4 prep --set-prefix "PATCH v2"
b4 send

git bisect 상세

# git bisect: 이진 검색(Binary Search)으로 버그 도입 커밋 찾기

# 수동 bisect
git bisect start
git bisect bad HEAD                # 현재 = 버그 있음
git bisect good v6.5               # v6.5 = 정상
# → git이 중간 커밋을 체크아웃
# → 빌드 & 테스트 후:
git bisect good                    # 또는 git bisect bad
# → 반복... (O(log n) 커밋)
git bisect reset                   # 완료 후 원래 브랜치로

# 자동 bisect (스크립트로 자동 판별)
git bisect start HEAD v6.5
git bisect run ./test-script.sh
# test-script.sh: 종료 코드 0 = good, 1-124 = bad, 125 = skip

# 자동 bisect 예시 스크립트
cat > test-bug.sh << 'EOF'
#!/bin/bash
make -j$(nproc) 2>/dev/null || exit 125    # 빌드 실패 = skip
# QEMU로 부팅 테스트
timeout 60 qemu-system-x86_64 \
    -kernel arch/x86/boot/bzImage \
    -initrd initramfs.gz \
    -append "console=ttyS0" \
    -nographic -m 1G 2>&1 | grep -q "BUG:" && exit 1
exit 0
EOF
chmod +x test-bug.sh
git bisect run ./test-bug.sh

IDE/에디터 설정 상세

커널 개발을 위한 에디터 설정은 코드 탐색, 자동 완성(Autocomplete), 정적 분석 통합이 핵심입니다. compile_commands.json을 생성하면 LSP(Language Server Protocol) 기반 도구가 정확한 의미 분석을 수행합니다.

VS Code 설정

# 1) compile_commands.json 생성 (필수)
scripts/clang-tools/gen_compile_commands.py
# 또는 bear 사용 (어떤 빌드 시스템이든 지원)
bear -- make -j$(nproc)

# 2) VS Code 확장 설치
# - clangd (C/C++ IntelliSense, 코드 완성, 네비게이션)
# - C/C++ (Microsoft, 대안)
# - Vim (Vim 키 바인딩)
# - GitLens (Git 통합)

# 3) .vscode/settings.json
{
    "clangd.path": "/usr/bin/clangd",
    "clangd.arguments": [
        "--background-index",
        "--compile-commands-dir=${workspaceFolder}",
        "--header-insertion=never",
        "--completion-style=detailed",
        "-j=4"
    ],
    "files.associations": {
        "*.h": "c"
    },
    "editor.tabSize": 8,
    "editor.insertSpaces": false,
    "editor.rulers": [80, 100],
    "files.trimTrailingWhitespace": true,
    "C_Cpp.intelliSenseEngine": "disabled"
}

Vim/Neovim 설정

" ~/.vimrc 또는 ~/.config/nvim/init.vim (커널 개발용)

" 커널 코딩 스타일
set tabstop=8
set shiftwidth=8
set noexpandtab
set textwidth=80
set colorcolumn=80,100
filetype plugin indent on
syntax on

" cscope 설정
if has("cscope")
    set csprg=/usr/bin/cscope
    set csto=0
    set cst
    set nocsverb
    if filereadable("cscope.out")
        cs add cscope.out
    endif
    set csverb

    " 키 매핑
    nmap <C-\>s :cs find s <C-R>=expand("<cword>")<CR><CR>
    nmap <C-\>g :cs find g <C-R>=expand("<cword>")<CR><CR>
    nmap <C-\>c :cs find c <C-R>=expand("<cword>")<CR><CR>
    nmap <C-\>d :cs find d <C-R>=expand("<cword>")<CR><CR>
endif

" ctags 설정
set tags=./tags;/

" Neovim LSP (clangd) — init.lua
" require('lspconfig').clangd.setup{
"     cmd = { "clangd", "--background-index",
"             "--compile-commands-dir=." },
" }

Emacs 설정

;; ~/.emacs.d/init.el (커널 개발용)

;; 커널 코딩 스타일
(defun linux-kernel-coding-style ()
  "Setup C coding style for Linux kernel."
  (setq indent-tabs-mode t)
  (setq tab-width 8)
  (setq c-basic-offset 8)
  (c-set-style "linux"))

(add-hook 'c-mode-hook 'linux-kernel-coding-style)

;; TAGS 사용 (etags)
;; M-. : 정의로 이동
;; M-* : 이전 위치로 복귀
;; make TAGS 로 인덱스 생성

;; eglot (내장 LSP 클라이언트, Emacs 29+)
(add-hook 'c-mode-hook 'eglot-ensure)
(setq eglot-server-programs
      '((c-mode . ("clangd" "--background-index"))))

가상화 기반 개발 환경

커널 개발에서 가상화(Virtualization)는 안전한 테스트 환경을 제공합니다. 버그가 있는 커널을 부팅해도 호스트 시스템에 영향이 없으며, 디버거 연결도 용이합니다.

QEMU

# QEMU 기본 실행 옵션 상세
qemu-system-x86_64 \
    -kernel arch/x86/boot/bzImage \       # 커널 이미지
    -initrd initramfs.gz \                 # 초기 RAM 디스크
    -append "console=ttyS0 nokaslr root=/dev/sda rw" \  # 커널 파라미터
    -nographic \                           # 그래픽 없이 시리얼 콘솔만
    -m 2G \                                # 메모리 2GB
    -smp 4 \                               # CPU 4코어
    -enable-kvm \                          # KVM 가속 (호스트 = Linux)
    -cpu host \                            # 호스트 CPU 기능 전달
    -s -S \                                # GDB 대기 (포트 1234)
    -drive file=rootfs.img,format=qcow2 \  # 디스크 이미지
    -netdev user,id=net0,hostfwd=tcp::2222-:22 \  # 포트 포워딩
    -device virtio-net-pci,netdev=net0

# QEMU 디스크 이미지 생성
qemu-img create -f qcow2 rootfs.img 10G
# debootstrap으로 루트 파일시스템 설치
sudo debootstrap --arch=amd64 bookworm /mnt/rootfs
# 또는 Syzkaller의 create-image.sh 사용

# ARM64 에뮬레이션
qemu-system-aarch64 \
    -M virt -cpu cortex-a57 \
    -kernel Image \
    -append "console=ttyAMA0" \
    -nographic -m 2G -smp 2

# RISC-V 에뮬레이션
qemu-system-riscv64 \
    -M virt -cpu rv64 \
    -kernel Image \
    -append "console=ttyS0" \
    -nographic -m 2G

virtme / virtme-ng

virtme는 현재 호스트의 루트 파일시스템을 그대로 사용하여 커널을 빠르게 부팅하는 도구입니다. 별도 디스크 이미지가 필요 없어 개발 사이클(Cycle)이 매우 빠릅니다.

# virtme-ng 설치
pip install virtme-ng

# 빠른 커널 부팅 (현재 호스트 파일시스템 사용)
vng --build --run
# 또는
virtme-run --kdir . --mods=auto

# 특정 커널 파라미터와 함께
virtme-run --kdir . --mods=auto \
    --append "nokaslr" \
    --memory 2G --cpus 4

# 스크립트 실행 후 종료
virtme-run --kdir . --mods=auto \
    --script-sh "dmesg | grep -i error; poweroff"

# KUnit 빠른 실행
./tools/testing/kunit/kunit.py run --arch=x86_64

UML (User Mode Linux)

# UML: 커널을 사용자 프로세스로 실행 (가장 빠른 커널 테스트 방법)

# UML 커널 빌드
make ARCH=um defconfig
make ARCH=um -j$(nproc)

# UML 실행
./linux rootfstype=hostfs rw init=/bin/bash

# UML + 네트워크
./linux rootfstype=hostfs rw \
    eth0=slirp,,/usr/bin/slirp-fullbolt

# KUnit에서 UML 사용 (기본값)
./tools/testing/kunit/kunit.py run  # 자동으로 ARCH=um 사용

# UML 장점
# - 가상화 불필요 (일반 프로세스)
# - GDB로 직접 디버깅 (gdb ./linux)
# - 빌드/실행 매우 빠름
# - KUnit 기본 백엔드
# UML 단점
# - 하드웨어 접근 불가
# - x86/x86_64만 지원
# - 일부 커널 기능 미지원 (KVM, 인터럽트 등)

CI/CD 시스템

커널 개발에서 지속적 통합(Continuous Integration)은 다양한 아키텍처와 설정 조합에서 빌드와 테스트를 자동화합니다. 주요 CI 시스템은 패치가 메인라인에 병합되기 전에 문제를 조기에 발견합니다.

KernelCI

KernelCI는 리눅스 재단이 후원하는 커널 CI 프로젝트입니다. 200개 이상의 보드에서 커널을 빌드하고 부팅 테스트를 수행합니다.

CI 시스템운영 주체주요 기능결과 접근
KernelCI Linux Foundation 빌드 + 부팅 테스트, 200+ 보드 kernelci.org
0-Day (Intel) Intel 빌드 오류, 성능 회귀, 정적 분석 메일링 리스트 자동 보고
LKFT (Linaro) Linaro ARM/ARM64 kselftest, LTP lkft.linaro.org
syzbot Google syzkaller 기반 자동 퍼징 syzkaller.appspot.com
CKI (Red Hat) Red Hat 빌드 + 기능 테스트 메일링 리스트 보고

0-Day CI (Intel)

0-Day는 Intel이 운영하는 빌드 봇(Build Bot)으로, 메인라인 커밋과 메일링 리스트 패치를 자동으로 빌드하여 컴파일 오류, 경고, 성능 회귀(Performance Regression)를 메일로 보고합니다.

# 0-Day 보고 예시 (메일 수신)
# Subject: [PATCH v2] driver: fix null deref
# From: kernel test robot <lkp@intel.com>
#
# Hi,
# Thank you for the patch!
#
# >> drivers/foo/bar.c:123:4: error: implicit function declaration
#
# All errors (new ones prefixed by >>):
# ...

# 로컬에서 0-Day와 유사한 검증 수행
# 여러 설정으로 빌드 테스트
for config in defconfig allmodconfig allyesconfig; do
    make mrproper
    make $config
    make -j$(nproc) 2>&1 | tee build_${config}.log
done

# 크로스 컴파일 테스트
for arch_cross in "arm64 aarch64-linux-gnu-" "riscv riscv64-linux-gnu-"; do
    set -- $arch_cross
    make mrproper
    ARCH=$1 CROSS_COMPILE=$2 make defconfig
    ARCH=$1 CROSS_COMPILE=$2 make -j$(nproc) 2>&1 | tee build_${1}.log
done
커널 CI/CD 파이프라인 개발자 패치 git send-email 메일링 리스트 LKML / 서브시스템 0-Day (Intel) 빌드 오류, 성능 회귀 KernelCI 빌드 + 부팅 테스트 syzbot 퍼징 (syzkaller) LKFT (Linaro) ARM kselftest, LTP 자동 보고 결과 메일 발송 PASS / FAIL / WARN 메인테이너 병합 결정 서브시스템 트리 linux-next Linus 메인라인 최종 병합 CI 실패 시 개발자에게 피드백 → 수정 후 재전송
패치 전송 → 메일링 리스트 → CI 자동 검증 → 메인테이너 병합 → 메인라인 흐름

실전 워크플로 가이드

각 개발 시나리오에 따라 도구를 효율적으로 조합하는 방법을 안내합니다.

시나리오 1: 첫 커널 패치 제출

# ① 개발 환경 준비
sudo apt install build-essential bc bison flex libelf-dev \
    libssl-dev libncurses-dev dwarves python3 git git-email
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux

# ② 빌드 검증
make defconfig
make -j$(nproc)

# ③ 수정 (예: 오타 수정)
git checkout -b fix-typo origin/master
# ... 코드 수정 ...

# ④ 빌드 & 검사
make -j$(nproc)
scripts/checkpatch.pl --file modified_file.c

# ⑤ 커밋 & 패치 생성
git add -p
git commit -s   # Signed-off-by 포함
git format-patch -1 HEAD

# ⑥ 검사 & 전송
scripts/checkpatch.pl 0001-*.patch
scripts/get_maintainer.pl 0001-*.patch
git send-email --to=your@email.com 0001-*.patch   # 테스트 발송
git send-email --to=... --cc=... 0001-*.patch       # 본 발송

시나리오 2: 커널 버그 추적

# ① 증상 기록
dmesg -T | tail -50 > bug_report.log

# ② 재현 환경 구축 (QEMU)
scripts/config --enable CONFIG_KASAN
scripts/config --enable CONFIG_DEBUG_INFO
scripts/config --disable CONFIG_RANDOMIZE_BASE
make -j$(nproc)
qemu-system-x86_64 -kernel arch/x86/boot/bzImage \
    -initrd initramfs.gz -append "console=ttyS0 nokaslr" \
    -nographic -m 2G -s

# ③ GDB로 디버깅
gdb vmlinux -ex "target remote :1234" -ex "lx-symbols"

# ④ git bisect로 원인 커밋 특정
git bisect start HEAD v6.5
git bisect run ./test-bug.sh

# ⑤ 수정 & 검증
# ... 코드 수정 ...
make C=1 -j$(nproc)                    # sparse 검사
./tools/testing/kunit/kunit.py run     # 단위 테스트

# ⑥ 패치 전송
git commit -s
git format-patch -1 HEAD
scripts/checkpatch.pl --strict 0001-*.patch

시나리오 3: 성능 분석 및 최적화

# ① 기준선(Baseline) 측정
perf stat -r 5 -- my_benchmark

# ② 핫스팟 식별
perf record -g -a -- my_benchmark
perf report
perf script | stackcollapse-perf.pl | flamegraph.pl > baseline.svg

# ③ 상세 분석
# 캐시 미스
perf stat -e L1-dcache-load-misses,LLC-load-misses -- my_benchmark
# 캐시 라인 경합
perf c2c record -- my_benchmark
# 구조체 패딩 분석
pahole -C hot_struct vmlinux

# ④ ftrace로 지연 측정
echo function_graph > /sys/kernel/debug/tracing/current_tracer
echo hot_function > /sys/kernel/debug/tracing/set_graph_function
echo 1 > /sys/kernel/debug/tracing/tracing_on
# ... 워크로드 실행 ...
cat /sys/kernel/debug/tracing/trace

# ⑤ 최적화 후 비교
perf stat -r 5 -- my_benchmark  # 최적화 후 측정
# Flame Graph 비교

도구 생태계 요약

개발 단계필수 도구권장 도구고급 도구
코드 작성 에디터 + ctags clangd + LSP GNU Global, cscope
빌드 GCC, make ccache, Clang distcc, Thin LTO
정적 검사 checkpatch.pl sparse, smatch Coccinelle, Clang Analyzer
동적 검사 KASAN UBSAN, lockdep KMSAN, KCSAN, KFENCE
테스트 QEMU 부팅 KUnit, kselftest LTP, syzkaller, xfstests
디버깅 dmesg, printk GDB + QEMU crash, kdump, KGDB
프로파일링 perf stat perf record, ftrace bpftrace, BCC, Flame Graph
패치 제출 git format-patch, git send-email b4, get_maintainer.pl lore.kernel.org, patchwork

커널 개발 도구 종합 요약

도구분류주요 용도핵심 명령/옵션
GCC/Clang빌드커널 컴파일make CC=clang LLVM=1
GDB디버깅커널/모듈 디버깅target remote :1234, lx-dmesg
QEMU가상화(Virtualization)빌드 커널 테스트-kernel -initrd -s -S
ftrace트레이싱함수/이벤트 추적/sys/kernel/debug/tracing/
perf프로파일링성능 분석, 카운터perf record -g, perf report
bpftrace트레이싱동적 eBPF 트레이싱bpftrace -e '...'
sparse정적 분석타입/잠금(Lock) 검사make C=1 또는 C=2
Coccinelle리팩터링패턴 기반 코드 변환make coccicheck
checkpatch.pl스타일코딩 스타일 검사./scripts/checkpatch.pl -f file.c
pahole/BTF분석구조체 레이아웃, BPFpahole -C task_struct vmlinux
KASAN런타임 검사메모리 오류 감지CONFIG_KASAN=y
lockdep런타임 검사데드락 감지CONFIG_LOCKDEP=y
KUnit테스트커널 단위 테스트make KUNIT=y, kunit.py run
kselftest테스트기능 회귀 테스트make -C tools/testing/selftests run_tests
crash사후 분석vmcore 분석crash vmlinux vmcore
Bootlin Elixir브라우저소스 크로스 레퍼런스elixir.bootlin.com

커널 모듈 개발 도구

커널 모듈(Kernel Module)은 커널을 재컴파일하지 않고 기능을 추가/제거할 수 있는 동적 로드(Dynamic Loading) 메커니즘입니다. 모듈 개발에 특화된 도구와 기법을 설명합니다.

외부 모듈 빌드

# 외부 모듈 Makefile 예시
obj-m += my_module.o
my_module-objs := main.o helper.o

# 다중 소스 파일 모듈
KDIR ?= /lib/modules/$(shell uname -r)/build

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

# 추가 플래그
ccflags-y += -DDEBUG -Werror
# 외부 모듈 빌드 및 로드
make -C /lib/modules/$(uname -r)/build M=$PWD modules
sudo insmod my_module.ko param1=value1
lsmod | grep my_module
sudo rmmod my_module

# 모듈 정보 확인
modinfo my_module.ko
# filename:       /path/to/my_module.ko
# description:    My test module
# author:         Developer Name
# license:        GPL
# depends:        
# vermagic:       6.x.0 SMP preempt mod_unload

# 모듈 의존성 확인
modprobe --show-depends my_module

# 모듈 심볼 확인
nm my_module.ko | grep ' T '  # 내보낸(exported) 심볼
/* 커널 모듈 기본 템플릿 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

static int param_value = 42;
module_param(param_value, int, 0644);
MODULE_PARM_DESC(param_value, "An integer parameter");

static int __init my_module_init(void)
{
    pr_info("my_module loaded, param=%d\n", param_value);
    return 0;
}

static void __exit my_module_exit(void)
{
    pr_info("my_module unloaded\n");
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Developer Name");
MODULE_DESCRIPTION("Example kernel module");
MODULE_VERSION("1.0");

모듈 디버깅

# 모듈 디버깅 단계

# 1) 동적 디버그 활성화
echo 'module my_module +p' > /sys/kernel/debug/dynamic_debug/control

# 2) QEMU에서 모듈 디버깅
# 모듈 로드 주소 확인
cat /sys/module/my_module/sections/.text
# 0xffffffffc0123000

# GDB에서 심볼 로드
(gdb) add-symbol-file my_module.ko 0xffffffffc0123000
(gdb) break my_function
(gdb) continue

# 3) ftrace로 모듈 함수 추적
echo ':mod:my_module' > /sys/kernel/debug/tracing/set_ftrace_filter
echo function > /sys/kernel/debug/tracing/current_tracer
echo 1 > /sys/kernel/debug/tracing/tracing_on

# 4) 모듈 로드/언로드 이벤트 추적
echo 1 > /sys/kernel/debug/tracing/events/module/module_load/enable
echo 1 > /sys/kernel/debug/tracing/events/module/module_free/enable

문서화 도구

커널 코드의 문서화는 유지보수성과 코드 리뷰 효율성에 직접적인 영향을 미칩니다. kernel-doc 형식의 주석(Comment)은 자동으로 API 문서를 생성하며, Sphinx를 통해 HTML/PDF로 변환됩니다.

kernel-doc 형식

/**
 * struct my_device - device information structure
 * @name: device name string
 * @id: unique device identifier
 * @flags: device state flags (see &my_device_flags)
 * @lock: protects concurrent access to @flags
 * @list: linked list node for device registry
 *
 * This structure holds all information for a single
 * managed device. Allocate with my_device_create()
 * and free with my_device_destroy().
 *
 * Context: Process context only. @lock must not be
 *          held when calling any function that may sleep.
 */
struct my_device {
    const char     *name;
    u32             id;
    unsigned long   flags;
    spinlock_t      lock;
    struct list_head list;
};

/**
 * my_device_create - allocate and initialize a device
 * @name: device name (copied internally)
 * @parent: parent device, or NULL for top-level
 *
 * Allocates a new &struct my_device and registers it
 * with the device subsystem. The caller must call
 * my_device_destroy() when done.
 *
 * Context: Process context. May sleep (GFP_KERNEL allocation).
 *
 * Return:
 * * pointer to new device  - success
 * * ERR_PTR(-ENOMEM)       - allocation failure
 * * ERR_PTR(-EEXIST)       - name already registered
 */
struct my_device *my_device_create(const char *name,
                                   struct device *parent);
# kernel-doc 검증
scripts/kernel-doc -none drivers/mydriver/myfile.c    # 형식 오류만 검사
scripts/kernel-doc -rst drivers/mydriver/myfile.c     # RST 출력
scripts/kernel-doc -man drivers/mydriver/myfile.c     # man 페이지 출력

# Sphinx로 HTML 문서 빌드
make htmldocs
# 결과: Documentation/output/index.html

# 특정 서브시스템만
make SPHINXDIRS="driver-api" htmldocs
make SPHINXDIRS="core-api" htmldocs
make SPHINXDIRS="networking" htmldocs

# kernel-doc 경고를 ERROR로 변환
make SPHINXOPTS="-W" htmldocs  # 경고가 있으면 빌드 실패

# PDF 문서 빌드 (LaTeX 필요)
make pdfdocs

RST 문서 작성

.. SPDX-License-Identifier: GPL-2.0

==========================
My Subsystem Documentation
==========================

Overview
========

This subsystem provides ...

API Reference
=============

.. kernel-doc:: drivers/mydriver/myfile.c
   :export:

.. kernel-doc:: include/linux/mydriver.h
   :internal:

Configuration
=============

.. kernel-doc:: drivers/mydriver/Kconfig

Tables
------

.. flat-table:: Device States
   :header-rows: 1

   * - State
     - Description
   * - IDLE
     - Device is not processing
   * - ACTIVE
     - Device is processing data

보안 감사 도구

커널 코드의 보안 취약점을 사전에 발견하기 위한 전용 도구들입니다.

KASAN + Stack Depot

# Stack Depot: 메모리 할당/해제 시 스택 트레이스 저장
scripts/config --enable CONFIG_KASAN
scripts/config --enable CONFIG_STACKDEPOT
scripts/config --enable CONFIG_PAGE_OWNER        # 페이지 소유자 추적

# 메모리 누수 감지
scripts/config --enable CONFIG_DEBUG_KMEMLEAK
make -j$(nproc)

# 부팅 후 메모리 누수 확인
echo scan > /sys/kernel/debug/kmemleak
cat /sys/kernel/debug/kmemleak

# 페이지 소유자 분석
echo 1 > /sys/kernel/debug/page_owner
cat /sys/kernel/debug/page_owner | head -100

보안 강화 설정 검증

# 커널 보안 설정 확인 스크립트
# https://github.com/a13xp0p0v/kernel-hardening-checker
pip install kernel-hardening-checker
kernel-hardening-checker -c /boot/config-$(uname -r)

# 주요 보안 CONFIG 옵션
scripts/config --enable CONFIG_STACKPROTECTOR_STRONG
scripts/config --enable CONFIG_FORTIFY_SOURCE
scripts/config --enable CONFIG_STRICT_KERNEL_RWX
scripts/config --enable CONFIG_RANDOMIZE_BASE       # KASLR
scripts/config --enable CONFIG_INIT_ON_ALLOC_DEFAULT_ON
scripts/config --enable CONFIG_INIT_ON_FREE_DEFAULT_ON
scripts/config --enable CONFIG_HARDENED_USERCOPY
scripts/config --enable CONFIG_SLAB_FREELIST_HARDENED

# 보안 관련 부팅 파라미터
# lockdown=confidentiality  — 커널 잠금 모드
# init_on_alloc=1           — 할당 시 0 초기화
# page_poison=1             — 해제 페이지 독소 주입
# slab_nomerge              — SLAB 캐시 병합 금지

커널 크기 분석 도구

임베디드(Embedded) 시스템이나 최적화가 필요한 환경에서는 커널 바이너리 크기를 분석하고 줄이는 것이 중요합니다.

# 커널 바이너리 크기 분석
size vmlinux
#    text    data     bss     dec     hex filename
# 12345678 2345678  567890 15259246 e8f4ee vmlinux

# 심볼별 크기 정렬 (상위 20개)
nm --size-sort -r vmlinux | head -20

# 섹션별 크기
readelf -S vmlinux | grep -E 'Size|\.text|\.data|\.rodata|\.bss'

# bloat-o-meter: 두 빌드 간 크기 변화 비교
scripts/bloat-o-meter vmlinux.old vmlinux
# add/remove: 5/3 grow/shrink: 12/8 up/down: 1234/-567 (667)
# Function                                     old     new   delta
# my_new_function                                 -     234    +234
# my_changed_function                           100     150     +50
# my_optimized_function                         200     150     -50

# 모듈별 크기
find /lib/modules/$(uname -r)/ -name '*.ko' -exec du -sh {} \; | sort -rh | head -20

# CONFIG_CC_OPTIMIZE_FOR_SIZE: 크기 최적화 (-Os)
scripts/config --enable CONFIG_CC_OPTIMIZE_FOR_SIZE

자주 발생하는 문제와 해결

문제증상원인해결
빌드 실패 fatal error: openssl/opensslv.h 개발 헤더 미설치 apt install libssl-dev
빌드 실패 BTF: .tmp_vmlinux.btf: pahole not found pahole(dwarves) 미설치 apt install dwarves
빌드 실패 No rule to make target 'debian/...' 소스 트리 오염 make mrproper
QEMU 부팅 실패 Kernel panic - not syncing: No init found initramfs 또는 rootfs 없음 initramfs 생성 또는 -initrd 지정
GDB 연결 실패 Remote connection closed QEMU에 -s 옵션 누락 qemu-system-x86_64 -s -S ...
GDB 심볼 없음 No debugging symbols found CONFIG_DEBUG_INFO 비활성 scripts/config --enable CONFIG_DEBUG_INFO
모듈 로드 실패 version magic mismatch 모듈과 커널 버전 불일치 동일 소스/설정으로 모듈 재빌드
sparse 경고 incorrect type in argument __user/__kernel 포인터 혼동 copy_from_user()/copy_to_user() 사용
perf 권한 Error: Access to performance monitoring 권한 부족 sysctl kernel.perf_event_paranoid=-1
ftrace 미동작 tracefs 빈 출력 debugfs 미마운트 mount -t debugfs none /sys/kernel/debug
checkpatch HTML non-ASCII characters 유니코드(Unicode) 문자 포함 ASCII 문자만 사용 (주석에서 제거)
send-email 실패 530 Authentication required SMTP 인증 설정 오류 앱 비밀번호 생성, .gitconfig 확인
💡

빌드 환경 진단 한 줄 명령:

# 빌드 도구 버전 일괄 확인
echo "GCC: $(gcc --version | head -1)" && \
echo "Make: $(make --version | head -1)" && \
echo "Binutils: $(ld --version | head -1)" && \
echo "Perl: $(perl --version | head -2 | tail -1)" && \
echo "Python: $(python3 --version)" && \
echo "pahole: $(pahole --version 2>/dev/null || echo 'not installed')"

도구 설치 빠른 참조

도구Debian/UbuntuFedora/RHEL소스 빌드
GCC apt install gcc dnf install gcc -
Clang/LLVM apt install clang lld llvm dnf install clang lld llvm apt.llvm.org
sparse apt install sparse dnf install sparse git.kernel.org
smatch - - repo.or.cz/smatch.git
Coccinelle apt install coccinelle dnf install coccinelle coccinelle.lip6.fr
pahole apt install dwarves dnf install dwarves github.com/acmel/dwarves
ccache apt install ccache dnf install ccache ccache.dev
cscope apt install cscope dnf install cscope -
GNU Global apt install global dnf install global gnu.org/software/global
crash apt install crash dnf install crash github.com/crash-utility
trace-cmd apt install trace-cmd dnf install trace-cmd git.kernel.org
perf apt install linux-perf dnf install perf tools/perf/ (커널 소스)
bpftrace apt install bpftrace dnf install bpftrace github.com/bpftrace
BCC apt install bpfcc-tools dnf install bcc-tools github.com/iovisor/bcc
b4 pip install b4 pip install b4 git.kernel.org/pub/scm/utils/b4
QEMU apt install qemu-system-x86 dnf install qemu-system-x86 qemu.org
virtme-ng pip install virtme-ng pip install virtme-ng github.com/arighi/virtme-ng
kdump apt install kdump-tools dnf install kexec-tools -
KernelShark apt install kernelshark dnf install kernelshark git.kernel.org

참고 자료

개발 도구와 관련된 다른 주제를 더 깊이 이해하고 싶다면 다음 문서를 참고하세요.