Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

37120
1703
402252


[리눅스커널] 커널 디버깅과 코드 학습: ftrace 는 커널 코드 분석의 안내자 3. 커널 디버깅과 코드 학습

ftrace 메시지는 텍스트 포멧입니다. 그래서 많은 분들이 해석하기 어렵다고 불평합니다.
하지만 ftrace 메시지는 바로 커널 코드 분석의 안내자일 수 있습니다. ftrace 이벤트 이름으로 어느 커널 소스 코드에서 이벤트를 출력하는지 알 수 있기 때문입니다.

실제 각 이벤트 별 ftrace를 출력하는 함수 이름은 다음 기준과 같습니다.
trace_ftrace_event_name

각 이벤트 별 출력함수는 다음 테이블에서 볼 수 있습니다.
ftrace 이벤트 출력함수
sched_switch trace_sched_switch
irq_handler_enter trace_irq_handler_enter
irq_handler_exit trace_irq_handler_exit

sched_switch 이벤트는 trace_sched_switch() 함수가 실행할 때 출력하고, irq_handler_enter와 irq_handler_exit이벤트는 각각 trace_irq_handler_enter()와 trace_irq_handler_exit() 함수가 실행할 때 출력합니다.

먼저 sched_switch ftrace 이벤트를 출력하는 코드를 검색하는 방법을 소개합니다.
리눅스 커널 코드에서 다음과 같이 trace_sched_switch 키워드로 검색해봅시다.
root@raspberrypi:/home/pi/src/RPi_kernel/linux# egrep -nr trace_sched_switch  *
kernel/sched/core.c:3380:              trace_sched_switch(preempt, prev, next);

검색 결과 위와 같이 kernel/sched/core.c 함수 3380 번째 줄이 보입니다.

해당 코드를 열어 보겠습니다.
[kernel/sched/core.c]
3295 static void __sched notrace __schedule(bool preempt)
3296 {
3297     struct task_struct *prev, *next;
3298     unsigned long *switch_count;
...
3360     if (likely(prev != next)) {
3361         rq->nr_switches++;
3362         rq->curr = next;
...
3378         ++*switch_count;
3379
3380         trace_sched_switch(preempt, prev, next);
3381
3382         /* Also unlocks the rq: */
3383         rq = context_switch(rq, prev, next, &rf);
3384     } else {
3385         rq->clock_update_flags &= ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP);
3386         rq_unlock_irq(rq, &rf);
3387     }

sched_switch는 __schedule() 함수 3380 번째 줄에서 출력한다는 사실을 알 수 있습니다.

이로 컨택스트 스위칭은 __schedule() 함수에서 context_switch() 코드를 실행할 때 수행된다는 사실을 알 수 있습니다. 이번에는 irq_handler_entry와 irq_handler_exit 이벤트 메시지를 어떤 커널 코드에서 출력하는지 살펴봅시다.

ftrace 이벤트를 출력하는 함수 이름 규칙에 따라 irq_handler_entry 이벤트 이름 앞에 trace_를 붙혀 소스 코드를 검색합시다.

검색 결과 __handle_irq_event_percpu() 함수에서 trace_irq_handler_entry() 함수 와 trace_irq_handler_exit() 함수를 호출합니다.

관련 코드는 다음과 같습니다.

 https://elixir.bootlin.com/linux/v4.19.30/source/kernel/irq/handle.c 
1 irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int *flags)
2 {
...
3 for_each_action_of_desc(desc, action) {
4 irqreturn_t res;
5
6 trace_irq_handler_entry(irq, action);
7 res = action->handler(irq, action->dev_id);
8 trace_irq_handler_exit(irq, action, res);


7 번째 줄 코드는 인터럽트 핸들러를 호출한다는 점을 기억합시다.


6 번째 줄에선 인터럽트 핸들러 호출 직전 trace_irq_handler_entry() 함수를 호출해 irq_handler_entry 이벤트를 출력합니다.

8 번째 줄에서는 인터럽트 핸들러 실행을 종료한 후 바로 trace_irq_handler_exit() 함수를 호출해 irq_handler_exit 이벤트를 출력합니다. 

임베디드 리눅스 입문자들이 가장 많이 하는 고민은 ‘리눅스 커널 어느 코드를 봐야 할 지 모르겠다.’입니다. ftrace 이벤트를 출력하는 함수 코드를 코드 분석의 출발점으로 삼으면 좋습니다. 

"혹시 궁금한 점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실히 답변 올려드리겠습니다!" 

Thanks,
Austin Kim(austindh.kim@gmail.com)

커널 디버깅과 코드 학습

디버깅이란
ftrace
   * ftrace란     


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


 



핑백

덧글

  • 멋부리는 눈의여왕 2022/11/09 01:22 # 답글

    ftrace에서 event와 function에 대해 질문 있습니다.

    제가 분석하고자 하는 function을 function_filter를 통해 지정을 하는데, event 설정은 왜 해야하나요?
    event가 발생됬을 때 제가 function_filter로 지정한 function이 실행되면 그것이 ftrace 로그에 기록이 되는 것인가요? 만약 function을 지정했는데 제가 설정한 event 내에 그 function이 실행되지 않으면 ftrace 로그에 기록이 되지 않나요?
댓글 입력 영역