Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

1638
469
422316


[리눅스][커널] 커널 크래시 분석은 왜 중요할까?! [Kernel]Crash: Troubleshooting


커널 크래시 분석을 잘하는 게 왜 중요할까요? 너무 당연한 질문인가요? 사실 세상에 너무 당연한 질문은 없습니다. 어쩌면 너무 당연한 질문에 답하려고 고민하다가 많은 걸 깨닫는 경우가 많은 것 같습니다.

여러분이 리눅스 드라이버를 개발하거나 새로운 리눅스 커널 버전을 포팅했다고 가정하겠습니다. 그런데 안타깝게도 부팅 도중 아래와 같은 로그를 출력하는 커널 크래시가 100% 발생하고 있습니다. 어떻게 분석해야 할지 몰라 하루 꼬박 밤을 새웠습니다. 참 이럴 때 난감하죠. 
[ 0.986578] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[ 0.986589] CPU: 0 PID: 1 Comm: swapper Not tainted 3.18.20 #1
[ 0.986610] [<c0013260>] (unwind_backtrace) from [<c0011440>] (show_stack+0x10/0x14)
[ 0.986624] [<c0011440>] (show_stack) from [<c05a68b4>] (panic+0xf0/0x2dc)
[ 0.986640] [<c05a68b4>] (panic) from [<c083c164>] (mount_block_root+0x26c/0x2b0)
[ 0.986655] [<c083c164>] (mount_block_root) from [<c083c37c>] (prepare_namespace+0x88/0x1ac)
[ 0.986668] [<c083c37c>] (prepare_namespace) from [<c083bdac>] (kernel_init_freeable+0x16c/0x1b0)
[ 0.986681] [<c083bdac>] (kernel_init_freeable) from [<c05a5d6c>] (kernel_init+0x8/0xe0)
[ 0.986693] [<c05a5d6c>] (kernel_init) from [<c000dda0>] (ret_from_fork+0x14/0x34)
[ 1.982696] Rebooting in 5 seconds..

그런데 어떤 동료가 산신령 같이 나타나서 같이 분석을 시작합니다. 이것은 rootfs 파일 시스템 마운트를 못해서 발생한 문제라고 하네요. 그리고 꼼꼼히 로그를 같이 보면서 파티션 마운트가 제대로 됐는지 부트 디바이스가 제대로 동작하는지 점검 후 문제가 해결됐습니다. 그러면 여러분 기분은 어떨까요? (아 조금 어려운 용어 “파티션 마운트”, “부트 디바이스”, “rootfs”가 보이죠? 이번 장 마지막에 친절히 설명했으니 참고하세요.)

그 동료에게 참 고맙게 생각하겠죠. 흠, 그런데 전 약간 다릅니다. 물론 이 동료에게 감사 표현을 할 것이 분명하죠. 이런 문제를 해결 못한 저를 엄청 자책할 겁니다. 앞으로 비슷한 커널 크래시가 나오면 바로 해결할 수 있도록 열심히 준비하면서 말이죠. 


일단 이 동료는 커널 크래시 문제를 해결했습니다. 다시 반복하자면 어떤 문제를 해결했죠. 임베디드 리눅스 개발자에게 문제 해결 능력은 가장 중요한 실무 역량입니다. 모든 회사가 애타게 찾는 개발자는 문제 해결 능력이 있는 개발자입니다. 문제 해결 능력이 있는 개발자를 당연히 실력 있다고 봐야 겠죠. 그런데 문제 해결을 하기 위한 첫걸음은 문제를 정확히 분석하는 능력입니다. 대부분 로그를 분석하는 과정에 답이 있는 경우가 많거든요. 실력 있는 개발자가 되기 위해서 커널 크래시 분석 능력이 키우는 게 중요합니다. 

리눅스 커뮤니티
그런데 가끔 바로 문제 해결을 못 할 때도 있습니다. 예를 들어 리눅스 버전을 새롭게 업그레이드했는데 커널 크래시가 발생할 경우죠. 콜스택 모두 우리 눈에 낯선 함수입니다. 이 경우 어떻게 해야 할까요? 

이럴 때 너무 자신을 자책하지 마세요. 리눅스 커널은 수 많은 서브 시스템으로 이루어져 있어 소스를 볼 수 있는 범위가 넓습니다. 그래서 모든 커널 코드를 잘 알기 힘듭니다. 그래서 리눅스 커널에는 분야별로 전문적으로 코드 리뷰를 하는 메인테이너가 있습니다. 우선 아래와 같은 정보를 포함해서 정밀히 분석해야 합니다. 
- 크래시가 발생한 정확한 코드 위치와 그 이유 
- 프로세스 이름 
- 인터럽트 컨택스트 여부 
- ftrace log 상세 분석 

이렇게 정밀하게 분석을 한 다음 리눅스 커뮤니티에 업로드를 하면 되죠. 리눅스 커널 메일링 리스트에 공유하면 좋습니다. 리눅스 커널은 강력한 커뮤니티가 큰 강점이라고 알려져 있죠. 그런데, 커널 로그만 복사해서 버그를 알리면 제대로 도움을 받을 수 있을까요? 프로세스 이름, 정확히 크래시가 난 코드와 함수 위치, 문제가 발생한 재현 경로를 자세히 올려야 도움을 받을 가능성이 높습니다. 그래서 커널 크래시 분석 능력이 중요합니다. 

효율적인 업무 진행
가끔 주말 동안 스트레스 테스트를 디바이스에 돌릴 경우가 있습니다. 안드로이드에서 몽키 테스트라고 하죠. 실제 유저가 디바이스를 사용하듯이 테스트 시나리오를 만들어 신뢰성 테스트를 하는 것입니다. 그런데 보드 20대 중에 10대가 커널 크래시를 맞으면 이 때 어떤 방식으로 일을 하는 게 효율적일까요? 10개의 코어 덤프를 리눅스 커널 커뮤니티나 벅질라 이슈에 올려야 할까요? 10개의 코어 덤프를 올리는 일도 보통 오래 시간이 걸리는 일이 아니죠. 10개의 코어 덤프를 크래시 유틸리티로 자세히 분석하면 커널 크래시의 원인은 2~3개로 좁혀지는 경우가 많습니다.

커널 크래시가 발생하는 패턴을 생각해 볼 필요가 있습니다. 우리는 보통 문제가 발생한 코드에서 바로 커널 크래시가 발생할 것이라 예상할 때가 있어요. 정말 문제 코드에서 딱 크래시가 발생하면 얼마나 좋을까요? 사실 그렇지 않습니다. 원인은 하나 인데 다양한 로그로 커널 크래시가 발생할 수 있습니다. 가장 대표적인 예가 슬랩 메모리를 누군가 깨 먹는 경우입니다. 아니면 특정 디바이스에서만 커널 크래시가 발생하는 경우도 있습니다. 갑자기 다양한 커널 로그로 랜덤하게 크래시가 발생하면 정말 죽을 맛이죠. 이럴 때 정밀하게 커널 크래시 디버깅을 하면 그 범인을 잡을 수 있습니다.

프로젝트 마감에 큰 걸림돌
프로젝트 마감이 내일인데 커널 크래시가 발생하면 여러분들은 기분은 어떨까요? 제품 출시에 걸림돌이 되는 가장 큰 이슈는 커널 크래시입니다. 사소한 버그는 첫 제품 출시 후 잡자고 고객사를 설득할 수 있습니다. 그런데 커널 크래시를 고객사에게 출시 후에 잡겠다고 협의를 할 수 있을까요? 실현 불가능한 현실이죠. 이렇게 프로젝트 막바지에 가끔 임베디드 리눅스 개발자들은 이 문제를 해결하기 전에 집에 못 가는 짜증나는 경험이 생각 날 겁니다.

저 같은 경우엔 예전에 어느 매니저님께서 담요와 베개를 갖고 제 옆에 오셨던 악몽이 되살아 나는군요. 이렇게 말씀하시면서요. “이 문제 해결하기 전까지 집에 못가.” 물론 그 당시 열심히 크래시 디버깅을 해서 문제의 원인을 잡아 집에 들어는 갔습니다.

커널 크래시 디버깅을 통한 학습
커널 디버깅을 하면 할수록 리눅스 커널과 디바이스 실력이 빨리 향상됩니다. 커널 크래시 디버깅을 잘하면 리눅스 커널 개발 능력이 업그레이드 되기 때문입니다. 리눅스 커뮤니티나 주위 고수들 중에 커널 크래시 디버깅을 잘 못하는 개발자를 본 적이 없습니다.

가끔은 커널 크래시 디버깅을 잘하는 개발자를 폄하하는 분도 만난 적이 있습니다. “커널 디버깅 툴(crash utility, Trace32, ftrace)을 잘 쓸 뿐이다.”라고 말이죠. 맞습니다. 리눅스 커널 고수들 정말 디버깅 툴 잘 씁니다. 그런데 리눅스 커널에 대한 깊은 이해와 커널 자료구조에 익숙하지 않고 절대 커널 크래시 디버깅을 능숙하게 할 수 없습니다.

#커널 크래시 디버깅 및 TroubleShooting



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

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

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



핑백

  • Linux Kernel(4.14) Hacks : [Linux][Kernel] 커널 크래시란 2018-06-18 21:23:45 #

    ... 커널 크래시란커널 크래시 분석은 왜 중요할까? 커널 패닉이란 말을 들어본 적이 있나요? 혹시 여러분이 임베디드 리눅스 개발자면 몇 번 쯤은 들어봤을 겁니다. 하지만, 리눅스를 자주 안 쓰거나 ... more

덧글

  • Paran Lee 2022/08/09 21:32 # 삭제 답글

    커널 패닉이 발생하지 않고, 아무것도 못하는 상태.. Task Hung 이 발생할 때 여러가지 방법을 찾아보다가

    크래시 덤프 vmcore 를 고의적으로 발생하여 가지고 분석하고 싶었는데 다음과 같은 설정을 발견했네요!

    sysctl -w kernel.hung_task_timeout_secs=30
    sysctl -w kernel.hung_task_panic=1
    sysctl -w kernel.panic=3

    CONFIG_DEFAULT_HUNG_TASK_TIMEOUT

    This option controls the default timeout (in seconds) used to determine when a task has become non-responsive and should be considered hung.
    It can be adjusted at runtime via the kernel.hung_task_timeout_secs sysctl or by writing a value to /proc/sys/kernel/hung_task_timeout_secs.
    A timeout of 0 disables the check. The default is two minutes. Keeping the default should be fine in most cases.


    커널 hung_task
    hung task 메커니즘은 커널 스레드 khungtaskd에 의해 구현되고 khungtaskd는 TASK_UNINTERRUPTIBLE 상태의 프로세스를 모니터링합니다.
    kernel.hung_task_timeout_secs(기본값: 120초) 시간 내에 계속 D 상태라면, hung task 프로세스 스택 정보가 출력됩니다.

    - https://intl.cloud.tencent.com/ko/document/product/213/41974

    나중에 시간이나면 khungtaskd 를 좀 더 분석해봐야겠어요.

    p.s.

    매직키라는 기능도 처음 알게 되었네요.. 그런데 task hung 상태에서는 잘 안 먹더라구요..

    Alt + PrintScreen + [CommandKey]예를 들면, kernel의 정보를 출력하기 싶다면 m이라는 CommandKey를 사용해주시면 된다.
    Alt키와 Print Screen키를 동시에 누르시고 m키를 누르시면 된다.

    이 콤보 키는 X windows아래에서는 실행할수 없다. 그렇기 때문에 text virtual terminal로 바꾸신 다음 실행하면 된다.

    Ctrl + Alt + F1로 첫번째 virtual console로 전환한다음 sysrq 조합키를 사용하시길 바란다.
    만약 serial console에서 이 콤보 키를 사용하려면 Break signal 를 보낸 다음 5초내로 sysrq 콤보 키를 사용하시면 된다.

    출처: https://rhlinux.tistory.com/17

  • Paran Lee 2022/08/09 21:48 # 삭제

    전에 hung task 관련 분석하셨던 포스팅이 있었네요! 감사합니다~
    - http://rousalome.egloos.com/9485593
  • Paran Lee 2022/08/09 21:52 # 삭제

    CONFIG_DETECT_HUNG_TASK
    CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE
    CONFIG_DEFAULT_HUNG_TASK_TIMEOUT

    v5.19
    https://elixir.bootlin.com/linux/v5.19/source/drivers/misc/lkdtm/bugs.c#L270

    static void lkdtm_HUNG_TASK(void)
    {
    set_current_state(TASK_UNINTERRUPTIBLE);
    schedule();
    }
  • Paran Lee 2022/08/09 21:58 # 삭제

    제가 리눅스 커널에서 말하는 hung 에 대해서 의미 정리가 잘 안되었네요.
    lkdtm 소스를 보면 너무 간단하고 TASK_UNINTERRUPTIBLE 관련하여 동현님 아래 포스팅 및 책에서 보았는데요!
    - http://rousalome.egloos.com/9990651

    음.. task hung 가 나면 단일 태스크가 아니라, 시스템 전체가 멈춘 것처럼 보일까요?
    감지하는 khungtaskd 가 돌고 있다는 말은 cpu 는 일하고 있을 거라고 생각하는데요..
    설정으로 hung task -> panic 이 발생하는 것도 그렇구요.

    hung 이 어떤 사건을 일으키는지 잘 모르겠습니다 헝..
  • AustinKim 2022/08/11 09:25 #

    HUNG 프로세스를 검출하는 루틴과 함수는 아래와 같은데요.

    커널에서 존재하는 모든 프로세스의 태스크 디스크립터를 체크하면서,
    120초 동안 TASK_UNINTERRUPTIBLE 상태로 슬립에 있는 프로세스가 있으면 커널 패닉을
    유발하는 동작이 핵심입니다.

    코드에 예외 처리 루틴이 많아 지저분해 보이는데, 핵심 코드는 몇 줄 밖에 안되네요.

    https://elixir.bootlin.com/linux/v5.15.50/source/kernel/hung_task.c

    * watchdog() 함수: 커널 스레드
    * check_hung_uninterruptible_tasks() 함수: HUNG 프로세스 검출 루틴

    static void check_hung_uninterruptible_tasks(unsigned long timeout)
    {
    ...
    for_each_process_thread(g, t) {
    ...
    /* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */
    if (READ_ONCE(t->__state) == TASK_UNINTERRUPTIBLE)
    check_hung_task(t, timeout);
    }
    unlock:
    rcu_read_unlock();
    if (hung_task_show_lock)
    debug_show_all_locks();

    if (hung_task_show_all_bt) {
    hung_task_show_all_bt = false;
    trigger_all_cpu_backtrace();
    }

    if (hung_task_call_panic)
    panic("hung_task: blocked tasks");
    }

    감사합니다.
  • Paran Lee 2022/08/09 21:39 # 삭제 답글

    2011 년도에 출판된 공개되어있는 crash 및 덤프 분석 관련 책이 입니다.
    서버 관점에서 나온 내용이고, 유용한 정보가 많아서 공유하면 좋을 것 같아요!
    - https://www.dedoimedo.com/computers/www.dedoimedo.com-crash-book.pdf
  • AustinKim 2022/08/11 09:26 #

    혹시 LKDTM을 통해 받은 vmcore가 더 있으면 공유해주세요.
    나중에 udemy에 디버깅 컨텐츠를 올려도 좋겠단 생각이 드네요.

    그럼 화이팅 하세요.
  • Paran Lee 2022/08/11 19:16 # 삭제 답글

    넵! 확인했습니다.

    crash utility 를 안쓰고 해커처럼 Ram Dump 만 가지고 strings 로 ascii 추출하는 방법도 있네요!
    -> hung 설정해도 도저히 커널이 패닉으로 가서 크래시 덤프나지 않아서 한동안 계속 찾았네요..
    다음에 기회되면 한번 정리해서 공유하겠습니다!
    설명해주셔서 감사합니다~!
댓글 입력 영역