Unix & Linux/ftrace

강력한 리눅스 커널 디버깅 툴 , ftrace 개론 - 작성중-

LEEHANDS 2022. 7. 11. 16:59
반응형

printk 또는 dump_stack 을 사용하면서 불편하답니다. 

저는 많이 안써봤습니다.

그래서 ftrace 를 많이 현업에서도 사용한다고 합니다.

 

주요 특징은

  1. 함수 호출 흐름을 소스코드 수정하지 않고도 보고싶다.
  2. 커널의 세부 실행 정보를 출력해줬으면 좋겠다.
  3. 1초에 수십번 호출해도 성능에 부담을 주지 않는다.
  4. 커널 로그도 함께 본다.
  5. 인터럽트, 스케쥴링, 커널 타이머 등의 커널 동작 상세히 추적
  6. 함수 필터를 지정하면 지정한 함수를 호출한 함수와 전체 콜 스택까지 출력
  7. 함수를 어느 프로세스가 실행하는지 알 수 있다.
  8. 함수가 실행된 시각 정보를 알 수 있다.
  9. ftrace 로그 활성화해도 시스템 동작에 부하를 거의 주지 않는다.

 

과연 그럴까 생각들정도로 강력한 것은 사실입니다.

 

How to do configuration

ftrace 에서 제공하는 nop, function, function_graph 트레이서를 쓰려면 관련코드가 커널이미지에 포함되어야 한다.

즉, ftrace 코드가 추가된 커널 소스를 빌드해야합니다.

이를 위해 다음과 같이 커널 설정 Configuration 을 활성화해야한다.

 

CONFIG_FTRACE=y
CONFIG_DYNAMIC_FTRACE=y 
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
CONFIG_IRQSOFF_TRACER=y
CONFIG_SCHED_TRACER=y
CONFIG_FUNCTION_PROFILER=y
CONFIG_STACK_TRACER=y
CONFIG_TRACER_SNAPSHOT=y

다행히? 라즈베리파이는 모든 Configuration 이 활성화 되어있다고합니다. 

 

Configuration 위치는 아래와 같다.

 

ftrace 설정파일을 어디서 확인할 수 있을까?

다음 경로에서 ftrace 드라이버 설정 폴더와 파일을 볼 수 있다.

/sys/kernel/debug/tracing

 

ftrace 설정

쉘스크립트를 통해 ftrace 설정을 해보도록합니다.

 

#!/bin/bash

echo 0 > /sys/kernel/debug/tracing/tracing_on
sleep 1
echo "tracing_off" 

echo 0 > /sys/kernel/debug/tracing/events/enable
sleep 1
echo "events disabled"

echo  secondary_start_kernel  > /sys/kernel/debug/tracing/set_ftrace_filter	
sleep 1
echo "set_ftrace_filter init"

echo function > /sys/kernel/debug/tracing/current_tracer
sleep 1
echo "function tracer enabled"

echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
echo 1 > /sys/kernel/debug/tracing/events/irq/irq_handler_entry/enable
echo 1 > /sys/kernel/debug/tracing/events/irq/irq_handler_exit/enable
sleep 1
echo "event enabled"

echo rpi_get_interrupt_info > /sys/kernel/debug/tracing/set_ftrace_filter
sleep 1
echo "rpi_get_interrupt_infois enabled"

#echo bcm2835_mmc_irq > /sys/kernel/debug/tracing/set_ftrace_filter
#sleep 1
#echo "bcm2835_mmc_irq is enabled"
echo "set_ftrace_filter enabled"

echo 1 > /sys/kernel/debug/tracing/options/func_stack_trace
echo 1 > /sys/kernel/debug/tracing/options/sym-offset
echo "function stack trace enabled"

echo 1 > /sys/kernel/debug/tracing/tracing_on
echo "tracing_on"

tracing_on : 트레이서 활성화/비활성화

tracer Option

  • nop : 기본 트레이서 , ftrace event only output
  • function : 함수 트레이서 , set_ftrace_filter 로 지정한 함수를 누가 호출하는지 출력
  • function_graph : 함수 실행시간과 세부 호출 정보를 그래프 포맷으로 출력

 

ftrace event setting

ftrace 에서 커널을 구성하는 서브 시스템과 기능별로 세부 동작을 출력하는 기능을 지원

이를 이벤트라고 합니다.

쉘 스크립트 코드를 보면

echo 0 > /sys/kernel/debug/tracing/events/enable
# ftrace all event disable

다음 코드는

echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable

echo 1 > /sys/kernel/debug/tracing/events/irq/irq_handler_entry/enable
echo 1 > /sys/kernel/debug/tracing/events/irq/irq_handler_exit/enable

스케쥴링 동작을 기록하는 sched_wakeup / sched_switch 이벤트를 활성화

인터럽트 핸들링의 시작과 종료시점을 기록하는 irq_handler_entry / irq_handler_exit 이벤트를 활성화하는 코드

 

필터 설정 : set_ftrace_filter

set_ftrace_filter 파일에 트레이싱하고싶은 함수를 지정합니다.

현재 트레이서를 function_graph 와 function 으로 설정할 경우 작동하는 파일

이를 가르켜 함수 필터를 지정한다고 표현

리눅스 커널에 존재하는 모든 함수를 필터로 지정할 수는 없고, available_filter_functions 파일에 포함된 함수만 지정할 수 있다.

 

라즈베리파이에서 available_filter_function 파일에 없는 함수를 set_ftrace_filter 파일에 지정하면 락업되니 주의

available_filter_function 파일의 위치는 '/sys/kernel/debug/tracing/available_filter_functions' 입니다.

 

echo  secondary_start_kernel  > /sys/kernel/debug/tracing/set_ftrace_filter

secondary_start_kernel() 함수를 필터로 설정합니다.

이 함수는 부팅도중에 한번 호출 됩니다. 더미로 secondary_start_kernel 함수를 필터로 설정하는 것입니다.

 

현재 트레이서를 function_graph 와 function으로 설정할 경우 set_ftrace_filter 에 지정한 함수를 트레이싱합니다.

그런데  sencondary_start_kernel 을 실행하지않고 set_ftrace_filter 를 설정하지 않으면 어떻게 동작할까요?

set_ftrace_filter 파일에 필터로 함수를 지정하지 않으면 모든 커널 내부 의 함수를 트레이싱합니다.

즉, 시스템이 수많은 커널 함수를 트레이싱하다가 결국 락업 상태에 빠지게 되고, 이를 방지하려는 코드 입니다.

 

※ 라즈베리파이에서 set_ftrace_filter 파일에 필터로 함수를 지정하지 ㅇ낳으면 시스템이 100% 락업

 

 ftrace 메시지는 어떻게 분석할까?

ftrace 를 제대로 활용하려면 먼저 ftrace 메시지를 읽고 해석하는 방법을 알아야한다.

ftrace 커널 동작을 세부 로그로 출력하기 때문에 임베디드 리북스 개발자에게 축복이라고 합니다.

ftrace 이벤트에서 가장많이 활용하는 sched_switch , sched_wakeup, irq_handler_entry, irq_handler_exit 이벤트를 해석하는 방법을 살펴봅니다.

 

pid 가 1723 인 cat 프로세스가 실행중이고 cpu 번호는 001 이다.

세부 컨텍스트 정보는 ftrace 메시지에서 항상 출력되면 4개의 알파벳으로 출력됩니다.

d n h/s 0~3

d : 인터럽트 비활성화   ==> 해당 CPU라인의 인터럽트를 비활성화한 상태입니다.

b : 선점 스케쥴링 요청  ==> 현재 프로세스가 선점 스케쥴링 될 수 있는 상태입니다.

h/s : 인터럽트 컨텍스트 ==> h 이면 인터럽트 컨텍스트 , s 이면 soft IRQ 컨텍스트

0~3 : preempt_count  ==> 프로세스의 thread_info 구조체의 preempt_count 필드 값

 

위와 같이 세부항목이 활성화 되어있지 않으면 "." 을 출력합니다.

 

ftrace 로그 추출하는 방법?

#!/bin/bash

echo 0 > /sys/kernel/debug/tracing/tracing_on
echo "ftrace off"

sleep 3

cp /sys/kernel/debug/tracing/trace . 
mv trace ftrace_log.c

각 이벤트를 출력하는 함수 목록

ftrace event Output function
sched_swich trace_sched_switch
irq_handler_entry trace_irq_handler_entry
irq_handler_exit trace_irq_handler_exit

sched_switch 이벤트는 trace_sched_switch()함수가 실행될 때 프로세스가 스케쥴링되는 정보를 출력

반응형