ARM Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

199239
1625
172596


[리눅스커널] 시그널: ftrace 시그널 이벤트(signal_generate/signal_deliver) 소개 12. 시그널

이번 소절에서 시그널 실행 흐름을 추적하는 ftrace event를 소개합니다.

ftrace는 시그널 동작에 대해 다음 이벤트를 지원합니다.
signal_generate: 시그널 생성
signal_deliver: 시그널 전달 후 실행 

먼저 시그널 관련 ftrace 이벤트를 활성화하는 방법을 소개하겠습니다.

시그널 ftrace 이벤트 키기

시그널 관련 이벤트는 다음 명령어로 활성화할 수 있습니다.
"echo 1 > /sys/kernel/debug/tracing/events/signal/signal_generate/enable"
"echo 1 > /sys/kernel/debug/tracing/events/signal/signal_deliver/enable"

시그널 ftrace 이벤트 로그 패턴와 실행 코드 확인하기

시그널 ftrace 이벤트 메시지는 다음 형식으로 출력합니다.
signal_generate: sig=9 errno=0 code=0 comm=bash pid=1240 grp=1 res=0
signal_deliver: sig=9 errno=0 code=0 sa_handler=0 sa_flags=0

각각 메시지의 의미와 메시지를 출력하는 함수 이름은 다음 테이블과 같습니다.
이벤트 종류 역할 실행 함수
signal_generate 시그널 생성 __send_signal()/send_sigqueue()
signal_deliver 시그널을 받아 처리 get_signal()

이번에는 각각 이벤트를 실행하는 커널 코드를 소개합니다. 

다음 signal_generate와 signal_deliver 이벤트를 출력하는 코드를 소개합니다.

먼저 signal_generate 이벤트 출력하는 코드를 보겠습니다.
[https://elixir.bootlin.com/linux/v4.19.30/source/kernel/signal.c]
01 static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
02  enum pid_type type, int from_ancestor_ns)
03 {
04  struct sigpending *pending;
05  struct sigqueue *q;
...
06 out_set:
07 signalfd_notify(t, sig);
08  sigaddset(&pending->signal, sig);
...
09 complete_signal(sig, t, type);
10 ret:
11 trace_signal_generate(sig, info, t, type != PIDTYPE_PID, result);
12 return ret;
13}

11 번째 줄 코드에서 trace_signal_generate() 함수를 실행할 때 signal_generate 이벤트 메시지를 출력합니다.

이어서 signal_deliver 이벤트를 출력하는 코드를 보겠습니다. 
[https://elixir.bootlin.com/linux/v4.19.30/source/kernel/signal.c]
01 bool get_signal(struct ksignal *ksig)
02 {
03 struct sighand_struct *sighand = current->sighand;
04 struct signal_struct *signal = current->signal;
05 int signr;
...
06 ka = &sighand->action[signr-1];
07
08 /* Trace actually delivered signals. */
09 trace_signal_deliver(signr, &ksig->info, ka);
10
11 if (ka->sa.sa_handler == SIG_IGN) /* Do nothing.  */

09 번째 줄 코드에서 trace_signal_deliver() 함수를 실행할 때 signal_deliver 이벤트 메시지를 출력합니다.

시그널 ftrace 이벤트 로그 분석하기

이어서 ftrace 로그로 시그널 이벤트를 분석하는 방법을 소개합니다.

분석할 로그는 다음과 같습니다. 
01 bash-833 [003] d... 3742.555155: sched_wakeup: comm=bash pid=1240 prio=120 target_cpu=003
02 bash-833 [003] d... 3742.555159: signal_generate: sig=9 errno=0 code=0 comm=bash pid=1240 grp=1 res=0
03 bash-833 [003] .... 3742.555161: sys_exit: NR 37 = 0
...
04 bash-833 [003] d... 3742.557372: sched_switch: prev_comm=bash prev_pid=833 prev_prio=120 prev_state=D ==> next_comm=bash next_pid=1240 next_prio=120
05 bash-1240 [003] .... 3742.557387: sys_exit: NR 335 = -514
06 bash-1240 [003] d... 3742.557411: signal_deliver: sig=9 errno=0 code=0 sa_handler=0 sa_flags=0

복잡히 보이는 로그는 2단계로 분류할 수 있습니다.
1단계: 시그널 생성 
2단계: 시그널 전달 받아 처리 

1단계: 시그널 생성 과정 
01번째 줄 로그를 보겠습니다.
01 bash-833 [003] d... 3742.555155: sched_wakeup: comm=bash pid=1240 prio=120 target_cpu=003

시그널을 생성하는 과정에서 "comm=bash pid=1240" 프로세스를 깨우는 동작입니다.

다음 02번째 줄 로그입니다.
02 bash-833 [003] d... 3742.555159: signal_generate: sig=9 errno=0 code=0 comm=bash pid=1240 grp=1 res=0

다음과 같은 시그널이 생성됐다는 메시지입니다.
전달된 시그널을 받을 프로세스: pid가 1240인 bash 프로세스 
시그널 종류: 9(SIGKILL)
시그널 그룹 유무: 1 

2단계: 시그널 전달 받아 처리 
이어서 2단계 로그 분석을 하겠습니다.

04번째 줄 로그를 보겠습니다.
04 bash-833 [003] d... 3742.557372: sched_switch: prev_comm=bash prev_pid=833 prev_prio=120 prev_state=D ==> next_comm=bash next_pid=1240 next_prio=120

1단계에서 pid가 1240인 bash 프로세스에게 시그널을 생성한 후 해당 프로세스를 깨웠습니다.
04번째 줄은 pid가 1240인 bash 프로세스로 스케줄링되는 동작입니다. 

다음 05~06번째 줄 로그를 보겠습니다. 
05 bash-1240 [003] .... 3742.557387: sys_exit: NR 335 = -514
06 bash-1240 [003] d... 3742.557411: signal_deliver: sig=9 errno=0 code=0 sa_handler=0 sa_flags=0

05번째 줄 로그로 335번 시스템 콜 핸들링을 마무리했다는 정보를 알 수 있습니다.
pid가 1240인 bash 프로세스가 ret_fast_syscall 레이블을 실행 중이란 사실을 추측할 수 있습니다. 

06번째 줄 로그는 다음과 같이 해석할 수 있습니다.  

    pid가 124인 bash 프로세스가 시그널을 전달 받았다.

이번 소절에서는 ftrace에서 지원하는 시그널 이벤트를 해석하는 방법을 소개했습니다. 
signal_generate
signal_deliver

여기서 한 가지 의문이 생깁니다. 

    실제 개발을 할 때 위와 같은 ftrace 이벤트는 쓸까?

이번 소절에 소개한 ftrace 시그널 이벤트는 실전 개발에서 유용하게 사용할 수 있으니 잘 기억한 후 활용하기를 바랍니다. 다음 상황에서 ftrace의 signal 이벤트를 활용하면 효율적으로 시그널 동작을 디버깅할 수 있습니다.
유저 공간에서 시그널 핸들러가 호출이 안될 때
시그널 발생 후 후속 처리에 문제가 있을 때


#Referene 시그널
시그널이란
시그널 설정은 어떻게 할까
시그널 생성 과정 함수 분석
프로세스는 언제 시그널을 받을까
시그널 전달과 처리는 어떻게 할까?
시그널 제어 suspend() 함수 분석 
시그널 ftrace 디버깅

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


핑백

덧글

댓글 입력 영역