언어 구조 및 프로그램 구성
BPFTrace 언어는 DTrace의 D 언어에서 영감을 받아 설계되었으며, 리눅스 커널의 eBPF 서브시스템과 상호작용하기 위한 추상화 계층을 제공합니다. 스크립트는 세 부분으로 구성됩니다: C 정의(헤더 및 구조체), 설정 블록 및 임포트, 액션 블록과 맵 선언입니다. 각 액션 블록은 프로브(kprobe, tracepoint 등), 옵션 조건문(predicate), 실행 코드로 이루어집니다.
컴파일 및 런타임 메커니즘
BPFTrace는 LLVM을 컴파일 백엔드로 사용하며, 스크립트를 eBPF 바이트코드로 변환합니다. libbpf 라이브러리를 통해 커널 BPF 서브시스템과 상호작용하고, kprobe, 하드웨어 성능 이벤트, 사용자 공간 동적 추적(uprobes, USDT) 등 다양한 계측점에 프로그램을 부착합니다. BPF 스택 제한(512바이트)과 검증기 제약 때문에 max_strlen, on_stack_limit 등의 설정 변수로 메모리 사용을 제어합니다.
실무 설계 고려사항
이벤트 주도 모델에서 여러 프로브 간 데이터 교환은 맵(map)을 통해 이루어지며, thread ID 키잉으로 스레드별 컨텍스트를 유지합니다. kprobe는 함수 진입점의 CPU 레지스터로부터 인자를 추출하지만, kretprobe는 반환값만 접근 가능하므로 진입 시점에 맵에 저장하는 패턴이 필수입니다. fentry/fexit 프로브는 BTF 타입 정보를 활용해 오버헤드를 감소시키며, tracepoint는 커널에서 정의된 안정적인 계측점을 제공합니다.