printk() 함수

printk() 함수는 리눅스 커널에서 메시지 출력과 디버깅을 위한 핵심 도구 중 가장 기본이 되는 도구이다. 이 글에서는 printk() 함수의 기능, 사용법, 예제 코드, 그리고 유용한 팁에 대해 알아본다.

printk() 함수

printk() 함수는 리눅스 커널에서 사용되는 표준 출력 함수로, 커널 내부에서 메시지를 출력하고 로그를 기록하는 데 사용된다. 이 함수는 사용자 공간의 printf() 함수와 유사한 형태를 갖추고 있으며, 커널 내부에서 메시지를 출력하는 가장 일반적인 방법으로 사용된다.

커널 로그 레벨(Log Level)

printk() 메시지에는 아래와 같은 로그 레벨이 있으며, 각 로그 레벨은 다른 중요도와 우선순위를 나타낸다.

Log LevelDefine의미
<0>KERN_EMEG시스템 Emergency 상황
<1>KERN_ALERT즉시 출력 메시지
<2>KERN_CRITCritical 에러 메시지
<3>KERN_ERR에러 메시지
<4>KERN_WARNINGWarning(경고) 메시지
<5>KERN_NOTICE정상 메시지
<6>KERN_INFO시스템 정보 메시지
<7>KERN_DEBUG디거깅 정보

커널 로그 레벨 설정

커널은 /proc/sys/kernel/printk 파일을 통해 로그 레벨을 설정할 수 있다.

필자의 리눅스 머신의 현재 설정값을 확인해 보면 다음과 같다.

$ cat /proc/sys/kernel/printk
4       4       1       7

출력된 값의 의미는 다음과 같다.

순서레벨의미
1Console Log Level이 값보다 높은 우선순위 메시지들을 Console에 출력
2Default Message Log Level우선순위를 지정하지 않은 메시들이 갖는 우선순위
3Minimum Console Log LevelConsole 로그 레벨이 설정될 수 있는 최소
4Default Console Log LevelConsole 로그의 디폴트 레벨

필자의 로그레벨 설정으로는 KERN_WARNING(4) 메시지 이상이 콘솔 로그에 남게 되고, 아래 printk문과 같이 따로 커널 로그를 지정하지 않고 사용하는 printk는 “Default Message Log Level”을 갖게 되므로 KERN_WARNING(4) 레벨을 갖게 된다.

printk("Hello, world!\n");

printk() 자료형에 따른 서식 지정

printk() 함수는 C언어의 printf()와 같이 자료형에 따른 출력 서식을 지정해야 한다. (https://www.kernel.org/doc/Documentation/printk-formats.txt)

변수 타입서식 지정자
int%d 또는 %x
unsigned int%u 또는 %x
long%ld 또는 %lx
unsigned long%lu 또는 %lx
long long%lld 또는 %llx
unsigned long long%llu 또는 %llx
size_t%zu 또는 %zx
ssize_t%zd 또는 %zx
s32%d 또는 %x
u32%u 또는 %x
s64%lld 또는 %llx
u64%llu 또는 %llx

커널 빌드시 printk에 전달하는 인자와 서식 지정자가 일치하지 않으면 컴파일 에러가 발생하니 주의해야 한다.

printk() 로 함수 심벌 정보 보기

다음은 printk() 함수를 사용하여 커널에서 메시지를 출력하는 간단한 예제 코드이다.

printk("process: %s\n", current->comm);
printk("[%s:%d] caller: %pS\n", __func__, __LINE__, (void*)__builtin_return_address(0));
  • line1: 프로세스의 이름을 출력한다. current는 현재 프로세스의 태스크 디스크립터 주소를 가르키는 매크로이다.
  • line2: __func__는 함수명을, __LINE__은 라인수, __builtin_return_address(0)은 현재 실행 중인 함수를 호출한 함수의 주소이다. %pS는 아규먼트로 지정한 주소를 심벌로 변환해 출력한다.

printk() 사용시 주의점

printk는 로드가 적지 않은 함수이기 때문에, 자주 호출되는 __schedule()함수와 같은 곳에서 사용하게 되면 시스템에 엄청난 부담을 주게되어 락업(Lock-up), 패닉(panic)을 포함한 여러 가지 문제들이 나타날 수 있다. 따라서, 실행 빈도가 많은 곳에서는 사용을 자제해야 한다. 자주 호출되는 함수라도 정보를 출력하고 콜스택을 확인하고자 한다면 ftrace 사용을 고려할 필요가 있다.

참고

답글 남기기