본문 바로가기

Core BSP 분석/리눅스 커널 핵심 분석

[리눅스커널] 커널 로그 레벨 수정 - console_printk 확인

리눅스 시스템을 개발할 때 가장 많이 활용하는 로그는 무엇일까요?
 
    * 커널 로그죠.
 
그런데 가끔 실전 개발에서 커널 로그 레벨을 조정해야 할 때가 있어요.
예를 들면 개발 버전이 아니라 릴리즈 버전을 배포할 때 변경하죠.
 
이번 시간에는 커널 로그 레벨을 3으로 내리는 방법에 대해 소개합니다.
 
코드 수정
 
커널 로그 레벨을 3으로 내리려면 다음과 같이 코드를 수정해야 합니다.
 
1. 커널 코드(컨피그)
 
다음과 같은 커널 컨피그를 추가해야 합니다.
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=3
 
2. 디바이스 트리 혹은 board make file
 
다음 커널 커맨드 라인이 추가 되도록 부트로더 코드를 수정해야 합니다.
rcupdate.rcu_expedited=2 rcu_nocbs=0-7 loglevel=3
 
커널 이미지를 로딩하는 부트로더는 LK(Little Kernel)와 uboot이 있는데요.
각 부트 로더에서 제공하는 함수를 사용해 커맨드 라인이 추가되도록 코드를 수정해야 합니다.
 
코드 수정 후 확인
 
이번에는 커널 로그 레벨이 제대로 설정됐는지 확인하기 위한 패치 코드를 소개합니다.
 
패치 코드는 아래와 같습니다.
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 766be12..54412a8 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -113,6 +113,17 @@ enum devkmsg_log_masks {
 
 static unsigned int __read_mostly devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT;
 
+
+void trace_console_printk(char *type)
+{
+       pr_emerg("[%s] ============emerg= %d %d %d %d===================== \n",
+                                               type, console_printk[0], console_printk[1], console_printk[2], console_printk[3]);
+
+}
+
 
diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c
index 0913b4d..f77947d 100644
--- a/kernel/printk/printk_safe.c
+++ b/kernel/printk/printk_safe.c
@@ -15,6 +15,7 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/kernel.h>
 #include <linux/preempt.h>
 #include <linux/spinlock.h>
 #include <linux/debug_locks.h>
@@ -398,6 +399,22 @@ __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
        return vprintk_default(fmt, args);
 }
 
+#define CONSOLE_TRACE_PERIOD           msecs_to_jiffies(HZ*20)
+#define INIT_CONSOLE_TRACE_PERIOD      msecs_to_jiffies(HZ*20)
+#include <linux/workqueue.h>
+
+static struct delayed_work console_trace_delayed_work;
+
+extern void trace_console_printk(char *type);
+
+static void console_trace_delayed_work_func(struct work_struct *work)
+{
+       trace_console_printk("delayed_work");
+
+       queue_delayed_work(system_highpri_wq, &console_trace_delayed_work,
+                                                       CONSOLE_TRACE_PERIOD);
+}
+
 void __init printk_safe_init(void)
 {
        int cpu;
@@ -414,6 +431,10 @@ void __init printk_safe_init(void)
 #endif
        }
 
+       INIT_DELAYED_WORK(&console_trace_delayed_work, console_trace_delayed_work_func);
+
+       queue_delayed_work(system_highpri_wq, &console_trace_delayed_work,
+                                               INIT_CONSOLE_TRACE_PERIOD);
 
딜레이 워크를 통해 2초 간격의 주기로 시간 정보를 출력하는 패치 코드입니다.
 
위 패치 코드에서 눈여겨 볼 점이 있는데, 커널 로그를 출력할 때 printk보단 pr_emerg이 좋다는 점입니다.
그 이유는 다음과 같습니다.;
 
    * 커널 로그 레벨이 낮아도 pr_emerg 로그를 반드시 커널이 출력해준다.
 
커널 로그 확인
 
패치 코드를 반영한 후 커널 로그로 console_printk 출력 결과를 확인하면 다음과 같습니다.
 
[    8.080092 / 01-01 00:00:08.079][0] [delayed_work] =========emerg= 3 3 1 7=====================
[   10.080068 / 01-01 00:00:10.079][0] [delayed_work] =========emerg= 3 3 1 7=====================
[   12.080069 / 01-01 00:00:12.079][0] [delayed_work] =========emerg= 3 3 1 7=====================
[   14.080064 / 01-01 00:00:14.079][0] [delayed_work] =========emerg= 3 3 1 7=====================
[   16.080067 / 01-01 00:00:16.079][0] [delayed_work] =========emerg= 3 3 1 7=====================
[   18.080093 / 01-01 00:00:18.079][0] [delayed_work] =========emerg= 3 3 1 7=====================
[   20.080084 / 01-01 00:00:20.079][0] [delayed_work] =========emerg= 3 3 1 7=====================