Linux Tutorial #16 커널 디버그 메세지 (printk)

리눅스 커널 소스를 가장 간단하게 디버깅 하는 방법은 소스코드 중간에 printk() 함수를 삽입하여 그 값을 직접 출력하는 것이다. 하지만 이러한 방식은 printk() 함수를 추가하고 삭제하는 과정이 매우 번거롭다. 리눅스 커널은 이러한 문제를 해결하고자 printk() 함수를 매크로로 정의하여 설정 상수와 레벨에 따라 조건 캄파일 하는 방식으로 관리한다.

1. 메세지 출력 레벨 조정

출력 레벨은 다음의 명령어를 입력하여 proc 파일 시스템에서 설정이 가능하다.

echo 4 > /proc/sys/kernel/printk
echo 8 > /proc/sys/kernel/printk

레벨이 낮을수록 긴급하고 위험한 수준의 메세지만 출력되고 레벨이 높을수록 대부분의 메세지(디버깅 메세지를 포함한)를 출력하게 된다. 따라서 레벨이 높아질수록 여러 메세지가 출력되므로 전체적인 시스템 성능은 저하된다.

2. 로그 레벨 (Log level)

이름문자열별칭 함수설명
KERN_EMERG"0"pr_emerg()긴급한 수준의 메세지를 출력
KERN_ALERT"1"pr_alert()경고 수준의 메세지를 출력
KERN_CRIT"2"pr_crit()치명적 수준의 메세지를 출력
KERN_ERR"3"pr_err()에러 수준의 메세지를 출력
KERN_WARNING"4"pr_warn()경고 수준의 메세지를 출력
KERN_NOTICE"5"pr_notice()주의 수준의 메세지를 출력
KERN_INFO"6"pr_info()설명 수준의 메세지를 출력
KERN_DEBUG"7"pr_debug 그리고 pr_devel()
만일 DEBUG가-정의되어 있다면
디버그 수준의 메세지를 출력
KERN_DEFAULT""-기본적인 커널 로그 레벨의 메세지를 출력
KERN_CONT"c"pr_cont()이전 로그 메세지와 같은 라인에서 출력

위 표는 printk 를 사용하는 pr_XXX 계열 매크로 함수들이 인자로 전달하는 값들이다. 실제 매크로 정의는 아래와 같이 이뤄진다:

위와 같이 로그 레벨 매크로를 printk 함수에 전달하며 호출한다.

함수와 로그 레벨 등은 include/linux/printk.hinclude/linux/kern_levels.h 파일에서 확인할 수 있다.

3. 로그 레벨 빌드 설정

위의 기능들은 리눅스 커널 소스를 빌드할 때 menuconfig 에서 설정이 가능하다. Kernel hacking > printk and dmesg options 순서대로 들어가면 아래의 설정 화면을 볼 수 있다.

필자는 위와 같이 설정되어 있으며, 기본으로 각각 7, 3, 4 로 설정된다.

4. 다이나믹 레벨 조정

다이나믹 레벨을 사용하면 특정 소스파일의 일부분의 디버그 메세지만 출력되도록 할 수 있다. 커널의 sys 파일 시스템을 통해 설정이 가능하다.

echo file test.c line 150-182 +p > /sys/kernel/dynamic_debug/control 

위와 같은 명령을 내리면 커널의 test.c 소스코드의 150 줄부터 182 줄 사이의 디버그 메세지만 출력된다.

echo file test.c function test_init +p > /sys/kernel/dynamic_debug/control

위와 같은 명령을 내리면 커널의 test.cc 소스코드 내에 있는 test_init 함수에 있는 디버그 메세지만 출력된다.

다이나믹 printk() 를 사용하려면 커널 menuconfig 값을 적절하게 설정해야 한다. 위에서 봤던 커널 로그 레벨 설정과 같은 페이지에 있으므로 해당 사진을 참조하길 바란다.

관련된 코드는 /include/linux/printk.h 에서 확인 가능하다:

출처

[책] 리눅스 커널 소스 해설: 기초 입문 (정재준 저)
[사이트] https://www.kernel.org/doc/html/latest/core-api/printk-basics.html

좋은 웹페이지 즐겨찾기