← Documents Documentation/core-api/printk-index.rst GitHub 원문 ↗

Linux 6.18.37 · Core API

Printk Index

실행 중인 커널과 모듈의 printk 형식을 debugfs에서 추적하는 index, metadata wrapper, KABI 비보장과 접두사 처리 방식을 설명합니다.

Source pathDocumentation/core-api/printk-index.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

printk-index.rst:1-137

Printk index는 실행 중인 `vmlinux`와 로드된 module에 포함된 printk format을 `/sys/kernel/debug/printk/index/` 아래에 공개합니다. 메시지의 level, source 위치, function과 format string을 함께 제공해 log 변경을 source 및 commit까지 추적할 수 있습니다.

개별 kernel message는 안정된 KABI가 아니며 코드와 함께 바뀝니다. Index는 메시지를 고정하는 계약이 아니라 사용자 공간 monitoring tool이 그 변화를 식별하고 대응하도록 돕는 장치입니다.

Metadata는 `.printk_index` ELF section에 저장되며 `__printk_index_emit()` wrapper를 거친 호출만 수집됩니다. 아직 모든 하위 시스템 wrapper가 지원되는 것은 아니므로 일부 format이 빠질 수 있습니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ============
4 Printk Index
5 ============
6
7 There are many ways to monitor the state of the system. One important
8 source of information is the system log. It provides a lot of information,
9 including more or less important warnings and error messages.
10
11 There are monitoring tools that filter and take action based on messages
12 logged.
13
14 The kernel messages are evolving together with the code. As a result,
15 particular kernel messages are not KABI and never will be!
16
17 It is a huge challenge for maintaining the system log monitors. It requires
18 knowing what messages were updated in a particular kernel version and why.
19 Finding these changes in the sources would require non-trivial parsers.
20 Also it would require matching the sources with the binary kernel which
21 is not always trivial. Various changes might be backported. Various kernel
22 versions might be used on different monitored systems.
23
24 This is where the printk index feature might become useful. It provides
25 a dump of printk formats used all over the source code used for the kernel
26 and modules on the running system. It is accessible at runtime via debugfs.
27
28 The printk index helps to find changes in the message formats. Also it helps
29 to track the strings back to the kernel sources and the related commit.
30
31
32 User Interface
33 ==============
34
35 The index of printk formats are split in into separate files. The files are
36 named according to the binaries where the printk formats are built-in. There
37 is always "vmlinux" and optionally also modules, for example::
38
39 /sys/kernel/debug/printk/index/vmlinux
40 /sys/kernel/debug/printk/index/ext4
41 /sys/kernel/debug/printk/index/scsi_mod
42
43 Note that only loaded modules are shown. Also printk formats from a module
44 might appear in "vmlinux" when the module is built-in.
45
46 The content is inspired by the dynamic debug interface and looks like::
47
48 $> head -1 /sys/kernel/debug/printk/index/vmlinux; shuf -n 5 vmlinux
49 # <level[,flags]> filename:line function "format"
50 <5> block/blk-settings.c:661 disk_stack_limits "%s: Warning: Device %s is misaligned\n"
51 <4> kernel/trace/trace.c:8296 trace_create_file "Could not create tracefs '%s' entry\n"
52 <6> arch/x86/kernel/hpet.c:144 _hpet_print_config "hpet: %s(%d):\n"
53 <6> init/do_mounts.c:605 prepare_namespace "Waiting for root device %s...\n"
54 <6> drivers/acpi/osl.c:1410 acpi_no_auto_serialize_setup "ACPI: auto-serialization disabled\n"
55
56 , where the meaning is:
57
58 - :level: log level value: 0-7 for particular severity, -1 as default,
59 'c' as continuous line without an explicit log level
60 - :flags: optional flags: currently only 'c' for KERN_CONT
61 - :filename\:line: source filename and line number of the related
62 printk() call. Note that there are many wrappers, for example,
63 pr_warn(), pr_warn_once(), dev_warn().
64 - :function: function name where the printk() call is used.
65 - :format: format string
66
67 The extra information makes it a bit harder to find differences
68 between various kernels. Especially the line number might change
69 very often. On the other hand, it helps a lot to confirm that
70 it is the same string or find the commit that is responsible
71 for eventual changes.
72
73
74 printk() Is Not a Stable KABI
75 =============================
76
77 Several developers are afraid that exporting all these implementation
78 details into the user space will transform particular printk() calls
79 into KABI.
80
81 But it is exactly the opposite. printk() calls must _not_ be KABI.
82 And the printk index helps user space tools to deal with this.
83
84
85 Subsystem specific printk wrappers
86 ==================================
87
88 The printk index is generated using extra metadata that are stored in
89 a dedicated .elf section ".printk_index". It is achieved using macro
90 wrappers doing __printk_index_emit() together with the real printk()
91 call. The same technique is used also for the metadata used by
92 the dynamic debug feature.
93
94 The metadata are stored for a particular message only when it is printed
95 using these special wrappers. It is implemented for the commonly
96 used printk() calls, including, for example, pr_warn(), or pr_once().
97
98 Additional changes are necessary for various subsystem specific wrappers
99 that call the original printk() via a common helper function. These needs
100 their own wrappers adding __printk_index_emit().
101
102 Only few subsystem specific wrappers have been updated so far,
103 for example, dev_printk(). As a result, the printk formats from
104 some subsystems can be missing in the printk index.
105
106
107 Subsystem specific prefix
108 =========================
109
110 The macro pr_fmt() macro allows to define a prefix that is printed
111 before the string generated by the related printk() calls.
112
113 Subsystem specific wrappers usually add even more complicated
114 prefixes.
115
116 These prefixes can be stored into the printk index metadata
117 by an optional parameter of __printk_index_emit(). The debugfs
118 interface might then show the printk formats including these prefixes.
119 For example, drivers/acpi/osl.c contains::
120
121 #define pr_fmt(fmt) "ACPI: OSL: " fmt
122
123 static int __init acpi_no_auto_serialize_setup(char *str)
124 {
125 acpi_gbl_auto_serialize_methods = FALSE;
126 pr_info("Auto-serialization disabled\n");
127
128 return 1;
129 }
130
131 This results in the following printk index entry::
132
133 <6> drivers/acpi/osl.c:1410 acpi_no_auto_serialize_setup "ACPI: auto-serialization disabled\n"
134
135 It helps matching messages from the real log with printk index.
136 Then the source file name, line number, and function name can
137 be used to match the string with the source code.
138

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Printk index 개요

1-31

SPDX 라이선스 식별자는 GPL-2.0입니다.

Printk Index

시스템 상태를 관찰하는 방법은 많으며, 중요한 정보원 가운데 하나가 system log입니다. System log는 중요도가 서로 다른 warning과 error message를 포함해 많은 정보를 제공합니다.

기록된 메시지를 필터링하고 그 내용에 따라 동작하는 monitoring tool도 있습니다.

Kernel message는 코드와 함께 계속 변화합니다. 따라서 개별 kernel message는 KABI가 아니며 앞으로도 KABI가 될 수 없습니다.

이 특성 때문에 system log monitor를 유지하기는 매우 어렵습니다. 특정 kernel version에서 어떤 메시지가 왜 바뀌었는지 알아야 합니다. Source에서 변경을 찾으려면 단순하지 않은 parser가 필요하고, 항상 간단하지 않은 작업인 source와 binary kernel의 일치 확인도 해야 합니다. 일부 변경은 backport될 수 있고 관찰 대상 시스템마다 서로 다른 kernel version을 사용할 수도 있습니다.

이때 printk index 기능이 유용합니다. 실행 중인 시스템의 kernel과 module을 빌드할 때 사용된 source code 전체의 printk format을 dump하며, runtime에 debugfs로 접근할 수 있습니다.

Printk index는 message format 변경을 찾고 문자열을 kernel source와 관련 commit까지 추적하는 데 도움을 줍니다.

사용자 인터페이스

32-73

사용자 인터페이스 (User Interface)

Printk format index는 별도 파일로 나뉩니다. 각 파일 이름은 해당 printk format이 내장된 binary를 따릅니다. `vmlinux` 파일은 항상 있고 module 파일은 선택적으로 존재합니다.

/sys/kernel/debug/printk/index/vmlinux
/sys/kernel/debug/printk/index/ext4
/sys/kernel/debug/printk/index/scsi_mod

로드된 module만 표시됩니다. 또한 module을 built-in으로 빌드하면 그 module의 printk format이 `vmlinux`에 나타날 수 있습니다.

파일 내용은 dynamic debug interface에서 착안했으며 다음과 같은 형태입니다.

$> head -1 /sys/kernel/debug/printk/index/vmlinux; shuf -n 5 vmlinux
# <level[,flags]> filename:line function "format"
<5> block/blk-settings.c:661 disk_stack_limits "%s: Warning: Device %s is misaligned\n"
<4> kernel/trace/trace.c:8296 trace_create_file "Could not create tracefs '%s' entry\n"
<6> arch/x86/kernel/hpet.c:144 _hpet_print_config "hpet: %s(%d):\n"
<6> init/do_mounts.c:605 prepare_namespace "Waiting for root device %s...\n"
<6> drivers/acpi/osl.c:1410 acpi_no_auto_serialize_setup "ACPI: auto-serialization disabled\n"

각 필드의 의미는 다음과 같습니다.

  • `level`: log level 값입니다. 특정 심각도는 0부터 7, 기본값은 -1, 명시적 log level 없이 이어지는 줄은 `c`입니다.
  • `flags`: 선택적 flag입니다. 현재는 `KERN_CONT`를 나타내는 `c`만 있습니다.
  • `filename:line`: 관련 `printk()` 호출의 source filename과 line number입니다. `pr_warn()`, `pr_warn_once()`, `dev_warn()` 등 여러 wrapper가 있다는 점에 유의하십시오.
  • `function`: `printk()` 호출이 사용된 함수 이름입니다.
  • `format`: format string입니다.

추가 정보 때문에 서로 다른 kernel 사이의 차이를 찾기가 조금 어려워지며 특히 line number는 자주 바뀔 수 있습니다. 반면 같은 문자열인지 확인하거나 변경을 일으킨 commit을 찾는 데는 큰 도움이 됩니다.

printk()는 안정된 KABI가 아님

74-84

`printk()`는 안정된 KABI가 아닙니다.

일부 개발자는 이러한 구현 세부 정보를 사용자 공간으로 모두 공개하면 개별 `printk()` 호출이 KABI로 굳어질 수 있다고 우려합니다.

그러나 실제 의미는 정반대입니다. `printk()` 호출은 KABI가 되어서는 안 되며, printk index는 사용자 공간 도구가 이 변화에 대응하도록 돕습니다.

하위 시스템 전용 printk wrapper

85-106

하위 시스템 전용 printk wrapper

Printk index는 전용 ELF section `.printk_index`에 저장된 추가 metadata로 생성됩니다. 실제 `printk()` 호출과 함께 `__printk_index_emit()`을 수행하는 macro wrapper로 이를 구현합니다. Dynamic debug 기능의 metadata도 같은 기법을 사용합니다.

특정 메시지의 metadata는 이 특별한 wrapper로 메시지를 출력할 때만 저장됩니다. `pr_warn()`과 `pr_once()` 등을 포함한 일반적인 `printk()` 호출에는 구현되어 있습니다.

공통 helper 함수로 원래 `printk()`를 호출하는 여러 하위 시스템 전용 wrapper에는 추가 변경이 필요합니다. 이러한 함수에는 `__printk_index_emit()`을 더하는 자체 wrapper가 있어야 합니다.

현재까지는 `dev_printk()` 같은 소수의 하위 시스템 전용 wrapper만 갱신되었습니다. 따라서 일부 하위 시스템의 printk format은 printk index에서 빠질 수 있습니다.

하위 시스템 전용 접두사

107-137

하위 시스템 전용 접두사

`pr_fmt()` 매크로는 관련 `printk()` 호출이 생성하는 문자열 앞에 출력할 접두사를 정의할 수 있게 합니다. 하위 시스템 전용 wrapper는 보통 이보다 더 복잡한 접두사를 추가합니다.

이러한 접두사는 `__printk_index_emit()`의 선택적 매개변수를 통해 printk index metadata에 저장할 수 있습니다. 그러면 debugfs interface가 접두사를 포함한 printk format을 표시할 수 있습니다. 예를 들어 `drivers/acpi/osl.c`에는 다음 코드가 있습니다.

#define pr_fmt(fmt) "ACPI: OSL: " fmt

static int __init acpi_no_auto_serialize_setup(char *str)
{
      acpi_gbl_auto_serialize_methods = FALSE;
      pr_info("Auto-serialization disabled\n");

      return 1;
}

그 결과 다음 printk index 항목이 만들어집니다.

<6> drivers/acpi/osl.c:1410 acpi_no_auto_serialize_setup "ACPI: auto-serialization disabled\n"

이는 실제 log 메시지와 printk index를 일치시키는 데 도움이 됩니다. 그런 다음 source filename, line number, function name을 이용해 문자열을 source code와 연결할 수 있습니다.