← Documents Documentation/process/4.Coding.rst GitHub 원문 ↗

Linux 6.18.37 · 개발 절차

커널 코드를 올바르게 작성하기

Coding style, abstraction, preprocessor, inline, locking, regression, 검증 도구, 문서화와 내부 API 변경을 설명합니다.

Source pathDocumentation/process/4.Coding.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

결국 평가받는 것은 code다

4.Coding.rst:3-16

Community를 고려한 설계 절차가 중요해도 kernel project의 결과는 실제 code로 증명된다. 다른 개발자는 code를 review하고 mainline에 merge할지 결정하므로 최종 성공은 code 품질에 달려 있다.

Coding style

4.Coding.rst:18-72

커널의 표준 style은 Documentation/process/coding-style.rst에 정의된다. 오래된 in-tree code 일부가 규칙을 따르지 않는다고 해서 새 code도 자유롭게 작성할 수 있다는 뜻은 아니다. Style이 맞지 않으면 많은 reviewer가 내용 검토 전에 reformat을 요구한다.

큰 code base에서는 어느 위치든 빠르게 읽을 수 있는 일관성이 필요하다. 회사의 의무 style과 충돌하더라도 mainline에 넣으려면 kernel style을 따라야 한다. Upstream 기여는 formatting을 포함해 code에 대한 일부 통제권을 community와 나누는 일이다.

반대로 기존 code를 style만 고치기 위한 patch도 피한다. 이런 reformat patch는 실제 변경을 방해하는 noise로 받아들여진다. 다른 목적의 code를 수정하면서 주변 style을 함께 바로잡는 것은 자연스럽지만 style 변경 자체가 목적이면 안 된다.

Style 문서는 절대 어길 수 없는 법은 아니다. 예를 들어 80 column에 맞추려고 나눈 line이 훨씬 읽기 어렵다면 더 읽기 좋은 표현을 택할 수 있다.

clang-format은 code 일부의 formatting, 전체 file의 실수 탐색, include 정렬, variable·macro 정렬과 text reflow를 도울 수 있다. EditorConfig를 지원하는 editor는 indentation과 line ending 같은 기본값을 자동 적용할 수 있다.

필요한 만큼만 abstraction하기

4.Coding.rst:74-106

커널 규모에서 abstraction은 필수지만 지나치거나 너무 이른 abstraction은 premature optimization만큼 해롭다. 실제 요구 수준까지만 추상화해야 한다.

모든 caller가 항상 0을 넘기는 function argument를 미래 flexibility를 위해 남기면 사용되지 않은 path가 눈치채지 못한 채 깨지거나, 실제 미래 요구가 처음 예상과 다를 수 있다. Kernel developer가 unused argument를 제거하는 이유이며 처음부터 넣지 않는 편이 낫다.

여러 OS에서 driver 본체를 공유하려고 hardware access를 숨기는 layer는 Linux code를 흐리고 성능 비용을 만들 수 있어 특히 환영받지 못한다.

반면 다른 subsystem에서 상당량의 code를 복사하려 한다면 library로 분리하거나 더 높은 layer에 공통 기능을 두어야 하는지 검토해야 한다. 같은 code를 커널 곳곳에 복제할 가치는 없다.

#ifdef와 C preprocessor

4.Coding.rst:108-133

Preprocessor는 C가 아니며 과도하게 사용하면 사람이 읽기 어렵고 compiler의 type·correctness 검사도 약해진다. Source file 곳곳에 #ifdef block을 흩뿌리는 대신 가능하면 header에 조건을 모은다.

기능이 없을 때 빈 function이 되도록 conditional code를 감싸면 compiler가 call을 제거하고 본체 흐름은 깨끗하게 유지된다.

Macro는 side effect가 있는 expression을 여러 번 평가할 수 있고 type safety가 없다. 가능한 경우 inline function을 사용하면 생성 code는 비슷하면서 argument 단일 평가와 compiler type checking을 얻는다.

Inline function의 실제 비용

4.Coding.rst:135-158

Function call을 없애는 효율만 보고 inline을 남발하면 각 call site에 code가 복제되어 kernel image가 커지고 instruction cache pressure가 늘어 오히려 느려질 수 있다. Inline function은 작고 드물게 사용해야 한다.

현대 hardware에서는 공간이 곧 시간일 수 있어 고전적인 단순 time/space tradeoff가 그대로 적용되지 않는다. 최신 compiler는 inline keyword와 별개로 실제 inline 여부를 적극 판단하므로 keyword 남발은 불필요할 수도 있다.

Concurrency와 locking

4.Coding.rst:160-191

Devicescape wireless stack은 GPL로 공개된 뒤 mainline까지 약 1년이 걸렸다. Corporate 내부에서 single-processor만 고려해 개발한 흔적이 있었고, 현재 mac80211이 되기 전에 multiprocessor용 locking scheme을 뒤늦게 추가해야 했기 때문이다.

현대 kernel에서는 single-processor system도 responsiveness 향상을 위한 concurrency가 존재한다. 여러 thread가 동시에 접근할 수 있는 data structure와 hardware register는 올바른 lock으로 보호해야 한다. 구현 뒤 locking을 덧붙이는 일은 처음부터 설계하는 것보다 훨씬 어렵다.

Kernel developer는 spinlock, mutex, RCU, atomic 등 available primitive의 context와 의미를 이해하고 맞는 도구를 골라야 한다. Concurrency를 고려하지 않은 code는 mainline merge가 어렵다.

Regression과 user-space ABI

4.Coding.rst:193-226

큰 개선을 위해 기존 사용자 일부를 깨뜨리는 변경도 regression이다. Mainline은 regression을 강하게 거부하며 빨리 고치지 못하면 원인 patch를 revert하는 것이 원칙이다.

새 system 10개를 지원하면서 기존 system 하나를 깨뜨리는 것이 이득이라는 계산은 받아들여지지 않는다. 새 문제를 만들어 bug를 고치면 실제 진전이 있었는지 알 수 없기 때문이다.

특히 user-space ABI regression은 심각하다. User space에 공개한 interface는 원칙적으로 영구 지원해야 하므로 처음 설계할 때부터 충분히 생각하고 명확히 문서화하며 넓게 review받아야 한다.

Code checking과 runtime debug 도구

4.Coding.rst:228-332

완전히 error-free인 code가 어렵더라도 mainline 전에 최대한 많은 문제를 자동으로 찾아야 한다. Computer가 미리 잡은 문제는 사용자 system에서 발생하지 않는다.

make KCFLAGS=-W
make C=1
make coccicheck
  • Compiler warning: review에 보낼 code는 warning이 없어야 한다. 원인을 이해하지 않고 warning만 숨기는 수정은 피한다.
  • FRAME_WARN: 지정 크기보다 큰 stack frame을 경고한다.
  • DEBUG_OBJECTS: kernel object lifetime과 잘못된 operation 순서를 추적한다.
  • DEBUG_SLAB: memory allocation과 사용 오류를 찾는다.
  • DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP, DEBUG_MUTEXES: 흔한 locking·context 오류를 찾는다.
  • lockdep: lock 획득·해제, lock ordering, interrupt context를 추적해 드문 deadlock 가능성을 미리 찾는다.
  • Fault injection: memory allocation 등을 의도적으로 실패시켜 평소 실행되지 않는 error recovery path를 test한다.
  • sparse: user/kernel address 혼동, endian type 혼합, bit flag와 integer 혼동 같은 static issue를 찾는다.
  • Coccinelle: semantic patch로 coding problem을 찾고 수정안을 제안하며 광범위한 API conversion에도 유용하다.
  • Cross compilation: 실제 board가 없어도 다른 architecture용 compile로 portability bug를 찾는다.

복잡한 locking이 있는 code는 제출 전에 lockdep을 켜고 실행해야 한다. Debug option 일부는 성능 비용이 크므로 항상 enable하지는 않지만 각 option의 검출 범위를 익혀 필요한 test에 사용해야 한다.

Patch와 API 문서화

4.Coding.rst:334-390

충분한 문서는 merge를 쉽게 하고 다른 developer와 사용자에게 도움을 준다. 많은 경우 문서 추가는 사실상 의무다.

  • Changelog: 해결하는 문제, solution 형태, 참여자, 성능 영향과 patch를 적용해야 하는 이유를 적는다.
  • 새 user-space interface: sysfs와 /proc을 포함해 Documentation/ABI/README 형식으로 설명한다.
  • 새 boot parameter: Documentation/admin-guide/kernel-parameters.rst에 추가한다.
  • 새 Kconfig option: 기능과 사용자가 언제 선택해야 하는지 설명하는 help text를 넣는다.
  • 외부에서 쓰는 internal API: subsystem의 kernel-doc comment를 유지하고 필요한 function에 추가한다.

새 code는 스스로 읽을 수 있어야 하며 comment는 미묘한 이유를 설명해야 한다. Verbose하게 code를 다시 말하는 comment는 필요 없다.

Memory barrier에는 왜 필요한지, data structure에는 locking rule, 주요 structure에는 전체 설계, 떨어진 code 사이의 숨은 dependency에는 관계를 적어야 한다. 겉보기에 불필요해 code janitor가 잘못 cleanup할 수 있는 부분에는 현재 형태의 이유를 남긴다.

Internal API 변경

4.Coding.rst:392-426

User-space binary interface와 달리 kernel internal API는 필요하면 바꿀 수 있다. API를 우회하고 있거나 필요한 기능이 없어 쓰지 못한다면 API 자체를 개선할 신호일 수 있다.

Internal API 변경 patch는 무엇을 왜 바꾸는지 충분히 설명하고 더 큰 feature patch 안에 숨기지 말고 별도 patch로 분리한다.

API를 바꾼 개발자는 그 변경으로 깨지는 모든 in-tree code를 함께 고쳐야 한다. 널리 쓰는 function이면 수백~수천 곳의 변경과 다른 개발자의 작업 conflict가 생길 수 있으므로 근거가 충분해야 한다. Coccinelle이 광범위한 변경을 도울 수 있다.

Incompatible change는 가능하면 갱신되지 않은 caller가 compiler error로 드러나게 설계한다. In-tree use를 빠짐없이 찾고 out-of-tree 개발자도 변경을 알아차리게 할 수 있다. Out-of-tree 지원 의무는 없지만 불필요하게 더 어렵게 만들 이유도 없다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. _development_coding:
2
3 Getting the code right
4 ======================
5
6 While there is much to be said for a solid and community-oriented design
7 process, the proof of any kernel development project is in the resulting
8 code. It is the code which will be examined by other developers and merged
9 (or not) into the mainline tree. So it is the quality of this code which
10 will determine the ultimate success of the project.
11
12 This section will examine the coding process. We'll start with a look at a
13 number of ways in which kernel developers can go wrong. Then the focus
14 will shift toward doing things right and the tools which can help in that
15 quest.
16
17
18 Pitfalls
19 ---------
20
21 Coding style
22 ************
23
24 The kernel has long had a standard coding style, described in
25 :ref:`Documentation/process/coding-style.rst <codingstyle>`. For much of
26 that time, the policies described in that file were taken as being, at most,
27 advisory. As a result, there is a substantial amount of code in the kernel
28 which does not meet the coding style guidelines. The presence of that code
29 leads to two independent hazards for kernel developers.
30
31 The first of these is to believe that the kernel coding standards do not
32 matter and are not enforced. The truth of the matter is that adding new
33 code to the kernel is very difficult if that code is not coded according to
34 the standard; many developers will request that the code be reformatted
35 before they will even review it. A code base as large as the kernel
36 requires some uniformity of code to make it possible for developers to
37 quickly understand any part of it. So there is no longer room for
38 strangely-formatted code.
39
40 Occasionally, the kernel's coding style will run into conflict with an
41 employer's mandated style. In such cases, the kernel's style will have to
42 win before the code can be merged. Putting code into the kernel means
43 giving up a degree of control in a number of ways - including control over
44 how the code is formatted.
45
46 The other trap is to assume that code which is already in the kernel is
47 urgently in need of coding style fixes. Developers may start to generate
48 reformatting patches as a way of gaining familiarity with the process, or
49 as a way of getting their name into the kernel changelogs - or both. But
50 pure coding style fixes are seen as noise by the development community;
51 they tend to get a chilly reception. So this type of patch is best
52 avoided. It is natural to fix the style of a piece of code while working
53 on it for other reasons, but coding style changes should not be made for
54 their own sake.
55
56 The coding style document also should not be read as an absolute law which
57 can never be transgressed. If there is a good reason to go against the
58 style (a line which becomes far less readable if split to fit within the
59 80-column limit, for example), just do it.
60
61 Note that you can also use the ``clang-format`` tool to help you with
62 these rules, to quickly re-format parts of your code automatically,
63 and to review full files in order to spot coding style mistakes,
64 typos and possible improvements. It is also handy for sorting ``#includes``,
65 for aligning variables/macros, for reflowing text and other similar tasks.
66 See the file :ref:`Documentation/dev-tools/clang-format.rst <clangformat>`
67 for more details.
68
69 Some basic editor settings, such as indentation and line endings, will be
70 set automatically if you are using an editor that is compatible with
71 EditorConfig. See the official EditorConfig website for more information:
72 https://editorconfig.org/
73
74 Abstraction layers
75 ******************
76
77 Computer Science professors teach students to make extensive use of
78 abstraction layers in the name of flexibility and information hiding.
79 Certainly the kernel makes extensive use of abstraction; no project
80 involving several million lines of code could do otherwise and survive.
81 But experience has shown that excessive or premature abstraction can be
82 just as harmful as premature optimization. Abstraction should be used to
83 the level required and no further.
84
85 At a simple level, consider a function which has an argument which is
86 always passed as zero by all callers. One could retain that argument just
87 in case somebody eventually needs to use the extra flexibility that it
88 provides. By that time, though, chances are good that the code which
89 implements this extra argument has been broken in some subtle way which was
90 never noticed - because it has never been used. Or, when the need for
91 extra flexibility arises, it does not do so in a way which matches the
92 programmer's early expectation. Kernel developers will routinely submit
93 patches to remove unused arguments; they should, in general, not be added
94 in the first place.
95
96 Abstraction layers which hide access to hardware - often to allow the bulk
97 of a driver to be used with multiple operating systems - are especially
98 frowned upon. Such layers obscure the code and may impose a performance
99 penalty; they do not belong in the Linux kernel.
100
101 On the other hand, if you find yourself copying significant amounts of code
102 from another kernel subsystem, it is time to ask whether it would, in fact,
103 make sense to pull out some of that code into a separate library or to
104 implement that functionality at a higher level. There is no value in
105 replicating the same code throughout the kernel.
106
107
108 #ifdef and preprocessor use in general
109 **************************************
110
111 The C preprocessor seems to present a powerful temptation to some C
112 programmers, who see it as a way to efficiently encode a great deal of
113 flexibility into a source file. But the preprocessor is not C, and heavy
114 use of it results in code which is much harder for others to read and
115 harder for the compiler to check for correctness. Heavy preprocessor use
116 is almost always a sign of code which needs some cleanup work.
117
118 Conditional compilation with #ifdef is, indeed, a powerful feature, and it
119 is used within the kernel. But there is little desire to see code which is
120 sprinkled liberally with #ifdef blocks. As a general rule, #ifdef use
121 should be confined to header files whenever possible.
122 Conditionally-compiled code can be confined to functions which, if the code
123 is not to be present, simply become empty. The compiler will then quietly
124 optimize out the call to the empty function. The result is far cleaner
125 code which is easier to follow.
126
127 C preprocessor macros present a number of hazards, including possible
128 multiple evaluation of expressions with side effects and no type safety.
129 If you are tempted to define a macro, consider creating an inline function
130 instead. The code which results will be the same, but inline functions are
131 easier to read, do not evaluate their arguments multiple times, and allow
132 the compiler to perform type checking on the arguments and return value.
133
134
135 Inline functions
136 ****************
137
138 Inline functions present a hazard of their own, though. Programmers can
139 become enamored of the perceived efficiency inherent in avoiding a function
140 call and fill a source file with inline functions. Those functions,
141 however, can actually reduce performance. Since their code is replicated
142 at each call site, they end up bloating the size of the compiled kernel.
143 That, in turn, creates pressure on the processor's memory caches, which can
144 slow execution dramatically. Inline functions, as a rule, should be quite
145 small and relatively rare. The cost of a function call, after all, is not
146 that high; the creation of large numbers of inline functions is a classic
147 example of premature optimization.
148
149 In general, kernel programmers ignore cache effects at their peril. The
150 classic time/space tradeoff taught in beginning data structures classes
151 often does not apply to contemporary hardware. Space *is* time, in that a
152 larger program will run slower than one which is more compact.
153
154 More recent compilers take an increasingly active role in deciding whether
155 a given function should actually be inlined or not. So the liberal
156 placement of "inline" keywords may not just be excessive; it could also be
157 irrelevant.
158
159
160 Locking
161 *******
162
163 In May, 2006, the "Devicescape" networking stack was, with great
164 fanfare, released under the GPL and made available for inclusion in the
165 mainline kernel. This donation was welcome news; support for wireless
166 networking in Linux was considered substandard at best, and the Devicescape
167 stack offered the promise of fixing that situation. Yet, this code did not
168 actually make it into the mainline until June, 2007 (2.6.22). What
169 happened?
170
171 This code showed a number of signs of having been developed behind
172 corporate doors. But one large problem in particular was that it was not
173 designed to work on multiprocessor systems. Before this networking stack
174 (now called mac80211) could be merged, a locking scheme needed to be
175 retrofitted onto it.
176
177 Once upon a time, Linux kernel code could be developed without thinking
178 about the concurrency issues presented by multiprocessor systems. Now,
179 however, this document is being written on a dual-core laptop. Even on
180 single-processor systems, work being done to improve responsiveness will
181 raise the level of concurrency within the kernel. The days when kernel
182 code could be written without thinking about locking are long past.
183
184 Any resource (data structures, hardware registers, etc.) which could be
185 accessed concurrently by more than one thread must be protected by a lock.
186 New code should be written with this requirement in mind; retrofitting
187 locking after the fact is a rather more difficult task. Kernel developers
188 should take the time to understand the available locking primitives well
189 enough to pick the right tool for the job. Code which shows a lack of
190 attention to concurrency will have a difficult path into the mainline.
191
192
193 Regressions
194 ***********
195
196 One final hazard worth mentioning is this: it can be tempting to make a
197 change (which may bring big improvements) which causes something to break
198 for existing users. This kind of change is called a "regression," and
199 regressions have become most unwelcome in the mainline kernel. With few
200 exceptions, changes which cause regressions will be backed out if the
201 regression cannot be fixed in a timely manner. Far better to avoid the
202 regression in the first place.
203
204 It is often argued that a regression can be justified if it causes things
205 to work for more people than it creates problems for. Why not make a
206 change if it brings new functionality to ten systems for each one it
207 breaks? The best answer to this question was expressed by Linus in July,
208 2007:
209
210 ::
211
212 So we don't fix bugs by introducing new problems. That way lies
213 madness, and nobody ever knows if you actually make any real
214 progress at all. Is it two steps forwards, one step back, or one
215 step forward and two steps back?
216
217 (https://lwn.net/Articles/243460/).
218
219 An especially unwelcome type of regression is any sort of change to the
220 user-space ABI. Once an interface has been exported to user space, it must
221 be supported indefinitely. This fact makes the creation of user-space
222 interfaces particularly challenging: since they cannot be changed in
223 incompatible ways, they must be done right the first time. For this
224 reason, a great deal of thought, clear documentation, and wide review for
225 user-space interfaces is always required.
226
227
228 Code checking tools
229 -------------------
230
231 For now, at least, the writing of error-free code remains an ideal that few
232 of us can reach. What we can hope to do, though, is to catch and fix as
233 many of those errors as possible before our code goes into the mainline
234 kernel. To that end, the kernel developers have put together an impressive
235 array of tools which can catch a wide variety of obscure problems in an
236 automated way. Any problem caught by the computer is a problem which will
237 not afflict a user later on, so it stands to reason that the automated
238 tools should be used whenever possible.
239
240 The first step is simply to heed the warnings produced by the compiler.
241 Contemporary versions of gcc can detect (and warn about) a large number of
242 potential errors. Quite often, these warnings point to real problems.
243 Code submitted for review should, as a rule, not produce any compiler
244 warnings. When silencing warnings, take care to understand the real cause
245 and try to avoid "fixes" which make the warning go away without addressing
246 its cause.
247
248 Note that not all compiler warnings are enabled by default. Build the
249 kernel with "make KCFLAGS=-W" to get the full set.
250
251 The kernel provides several configuration options which turn on debugging
252 features; most of these are found in the "kernel hacking" submenu. Several
253 of these options should be turned on for any kernel used for development or
254 testing purposes. In particular, you should turn on:
255
256 - FRAME_WARN to get warnings for stack frames larger than a given amount.
257 The output generated can be verbose, but one need not worry about
258 warnings from other parts of the kernel.
259
260 - DEBUG_OBJECTS will add code to track the lifetime of various objects
261 created by the kernel and warn when things are done out of order. If
262 you are adding a subsystem which creates (and exports) complex objects
263 of its own, consider adding support for the object debugging
264 infrastructure.
265
266 - DEBUG_SLAB can find a variety of memory allocation and use errors; it
267 should be used on most development kernels.
268
269 - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP, and DEBUG_MUTEXES will find a
270 number of common locking errors.
271
272 There are quite a few other debugging options, some of which will be
273 discussed below. Some of them have a significant performance impact and
274 should not be used all of the time. But some time spent learning the
275 available options will likely be paid back many times over in short order.
276
277 One of the heavier debugging tools is the locking checker, or "lockdep."
278 This tool will track the acquisition and release of every lock (spinlock or
279 mutex) in the system, the order in which locks are acquired relative to
280 each other, the current interrupt environment, and more. It can then
281 ensure that locks are always acquired in the same order, that the same
282 interrupt assumptions apply in all situations, and so on. In other words,
283 lockdep can find a number of scenarios in which the system could, on rare
284 occasion, deadlock. This kind of problem can be painful (for both
285 developers and users) in a deployed system; lockdep allows them to be found
286 in an automated manner ahead of time. Code with any sort of non-trivial
287 locking should be run with lockdep enabled before being submitted for
288 inclusion.
289
290 As a diligent kernel programmer, you will, beyond doubt, check the return
291 status of any operation (such as a memory allocation) which can fail. The
292 fact of the matter, though, is that the resulting failure recovery paths
293 are, probably, completely untested. Untested code tends to be broken code;
294 you could be much more confident of your code if all those error-handling
295 paths had been exercised a few times.
296
297 The kernel provides a fault injection framework which can do exactly that,
298 especially where memory allocations are involved. With fault injection
299 enabled, a configurable percentage of memory allocations will be made to
300 fail; these failures can be restricted to a specific range of code.
301 Running with fault injection enabled allows the programmer to see how the
302 code responds when things go badly. See
303 Documentation/fault-injection/fault-injection.rst for more information on
304 how to use this facility.
305
306 Other kinds of errors can be found with the "sparse" static analysis tool.
307 With sparse, the programmer can be warned about confusion between
308 user-space and kernel-space addresses, mixture of big-endian and
309 small-endian quantities, the passing of integer values where a set of bit
310 flags is expected, and so on. Sparse must be installed separately (it can
311 be found at https://sparse.wiki.kernel.org/index.php/Main_Page if your
312 distributor does not package it); it can then be run on the code by adding
313 "C=1" to your make command.
314
315 The "Coccinelle" tool (http://coccinelle.lip6.fr/) is able to find a wide
316 variety of potential coding problems; it can also propose fixes for those
317 problems. Quite a few "semantic patches" for the kernel have been packaged
318 under the scripts/coccinelle directory; running "make coccicheck" will run
319 through those semantic patches and report on any problems found. See
320 :ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>`
321 for more information.
322
323 Other kinds of portability errors are best found by compiling your code for
324 other architectures. If you do not happen to have an S/390 system or a
325 Blackfin development board handy, you can still perform the compilation
326 step. A large set of cross compilers for x86 systems can be found at
327
328 https://www.kernel.org/pub/tools/crosstool/
329
330 Some time spent installing and using these compilers will help avoid
331 embarrassment later.
332
333
334 Documentation
335 -------------
336
337 Documentation has often been more the exception than the rule with kernel
338 development. Even so, adequate documentation will help to ease the merging
339 of new code into the kernel, make life easier for other developers, and
340 will be helpful for your users. In many cases, the addition of
341 documentation has become essentially mandatory.
342
343 The first piece of documentation for any patch is its associated
344 changelog. Log entries should describe the problem being solved, the form
345 of the solution, the people who worked on the patch, any relevant
346 effects on performance, and anything else that might be needed to
347 understand the patch. Be sure that the changelog says *why* the patch is
348 worth applying; a surprising number of developers fail to provide that
349 information.
350
351 Any code which adds a new user-space interface - including new sysfs or
352 /proc files - should include documentation of that interface which enables
353 user-space developers to know what they are working with. See
354 Documentation/ABI/README for a description of how this documentation should
355 be formatted and what information needs to be provided.
356
357 The file :ref:`Documentation/admin-guide/kernel-parameters.rst
358 <kernelparameters>` describes all of the kernel's boot-time parameters.
359 Any patch which adds new parameters should add the appropriate entries to
360 this file.
361
362 Any new configuration options must be accompanied by help text which
363 clearly explains the options and when the user might want to select them.
364
365 Internal API information for many subsystems is documented by way of
366 specially-formatted comments; these comments can be extracted and formatted
367 in a number of ways by the "kernel-doc" script. If you are working within
368 a subsystem which has kerneldoc comments, you should maintain them and add
369 them, as appropriate, for externally-available functions. Even in areas
370 which have not been so documented, there is no harm in adding kerneldoc
371 comments for the future; indeed, this can be a useful activity for
372 beginning kernel developers. The format of these comments, along with some
373 information on how to create kerneldoc templates can be found at
374 :ref:`Documentation/doc-guide/ <doc_guide>`.
375
376 Anybody who reads through a significant amount of existing kernel code will
377 note that, often, comments are most notable by their absence. Once again,
378 the expectations for new code are higher than they were in the past;
379 merging uncommented code will be harder. That said, there is little desire
380 for verbosely-commented code. The code should, itself, be readable, with
381 comments explaining the more subtle aspects.
382
383 Certain things should always be commented. Uses of memory barriers should
384 be accompanied by a line explaining why the barrier is necessary. The
385 locking rules for data structures generally need to be explained somewhere.
386 Major data structures need comprehensive documentation in general.
387 Non-obvious dependencies between separate bits of code should be pointed
388 out. Anything which might tempt a code janitor to make an incorrect
389 "cleanup" needs a comment saying why it is done the way it is. And so on.
390
391
392 Internal API changes
393 --------------------
394
395 The binary interface provided by the kernel to user space cannot be broken
396 except under the most severe circumstances. The kernel's internal
397 programming interfaces, instead, are highly fluid and can be changed when
398 the need arises. If you find yourself having to work around a kernel API,
399 or simply not using a specific functionality because it does not meet your
400 needs, that may be a sign that the API needs to change. As a kernel
401 developer, you are empowered to make such changes.
402
403 There are, of course, some catches. API changes can be made, but they need
404 to be well justified. So any patch making an internal API change should be
405 accompanied by a description of what the change is and why it is
406 necessary. This kind of change should also be broken out into a separate
407 patch, rather than buried within a larger patch.
408
409 The other catch is that a developer who changes an internal API is
410 generally charged with the task of fixing any code within the kernel tree
411 which is broken by the change. For a widely-used function, this duty can
412 lead to literally hundreds or thousands of changes - many of which are
413 likely to conflict with work being done by other developers. Needless to
414 say, this can be a large job, so it is best to be sure that the
415 justification is solid. Note that the Coccinelle tool can help with
416 wide-ranging API changes.
417
418 When making an incompatible API change, one should, whenever possible,
419 ensure that code which has not been updated is caught by the compiler.
420 This will help you to be sure that you have found all in-tree uses of that
421 interface. It will also alert developers of out-of-tree code that there is
422 a change that they need to respond to. Supporting out-of-tree code is not
423 something that kernel developers need to be worried about, but we also do
424 not have to make life harder for out-of-tree developers than it needs to
425 be.
426

3. 한국어 전문 번역

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

올바른 코드를 만드는 일

1-15

견고하고 community 중심적인 설계 절차가 중요하지만, kernel 개발 project의 성패를 최종적으로 증명하는 것은 그 결과로 나온 code다. 다른 개발자는 설계 의도만이 아니라 실제 code를 검토하고, 그 code를 mainline tree에 merge할지 결정한다. 따라서 project가 궁극적으로 성공하는지는 code의 품질에 달려 있다.

이 문서는 coding 과정에서 kernel 개발자가 흔히 빠지는 함정을 먼저 살펴본다. 이어서 올바른 구현 방향과, 문제를 mainline에 보내기 전에 찾아내는 데 도움이 되는 도구를 설명한다.

Coding style

18-72

Kernel에는 오래전부터 Documentation/process/coding-style.rst에 정리된 표준 coding style이 있다. 과거에는 이 정책을 강제 규칙이 아니라 권고 정도로 취급한 시기가 길었고, 그 결과 현재 tree에도 지침을 따르지 않는 code가 상당량 남아 있다. 기존 code의 이런 모습은 개발자에게 서로 독립적인 두 가지 함정을 만든다.

첫 번째 함정은 kernel coding 표준이 중요하지 않으며 실제 review에서도 강제되지 않는다고 믿는 것이다. 현실은 반대다. 새 code가 표준에 맞게 작성되지 않았다면 kernel에 추가하기가 매우 어렵다. 많은 개발자는 내용 검토를 시작하기도 전에 먼저 형식을 고치라고 요청한다. Kernel처럼 거대한 code base에서 어느 영역이든 빠르게 이해하려면 일정한 형식이 필요하므로, 특이한 개인식 formatting을 허용할 여지가 없다.

회사에서 의무화한 style과 kernel style이 충돌할 때도 있다. 그 code를 kernel에 merge하려면 kernel style이 우선해야 한다. Code를 kernel에 넣는다는 것은 여러 측면에서 통제권 일부를 넘기는 일이며, code formatting을 결정하는 권한도 여기에 포함된다.

두 번째 함정은 이미 kernel 안에 있는 code가 coding style 수정부터 시급히 필요하다고 생각하는 것이다. 개발 절차를 익히거나 changelog에 이름을 남기기 위해 reformatting patch를 만들 수 있지만, community는 기능 변화가 없는 순수 style 수정은 대개 noise로 본다. 다른 이유로 code를 수정하면서 그 주변 style을 함께 바로잡는 것은 자연스럽지만, style 변경만을 목적으로 한 patch는 피하는 편이 좋다.

Coding style 문서를 절대로 어길 수 없는 법률처럼 읽어서도 안 된다. 예를 들어 80-column 제한에 맞추려고 줄을 나누었더니 훨씬 읽기 어려워진다면, 명확한 이유를 가지고 제한을 벗어날 수 있다.

clang-format은 규칙에 맞춰 code 일부를 빠르게 자동 정렬하고, 파일 전체에서 style 오류·오타·개선 후보를 찾는 데 쓸 수 있다. #include 정렬, 변수와 macro 정렬, text reflow 같은 작업에도 유용하다. 자세한 내용은 Documentation/dev-tools/clang-format.rst를 참고한다.

EditorConfig를 지원하는 editor라면 indentation이나 line ending 같은 기본 설정이 자동으로 적용된다. 추가 정보는 https://editorconfig.org/ 에서 확인할 수 있다.

Abstraction layer

74-105

Computer Science 교육에서는 flexibility와 information hiding을 위해 abstraction layer를 폭넓게 사용하라고 가르친다. 수백만 line의 code로 이루어진 kernel 역시 abstraction 없이 유지될 수 없다. 그러나 경험상 지나치거나 너무 이른 abstraction은 premature optimization만큼 해로울 수 있다. 필요한 수준까지만 추상화하고 그 이상은 만들지 않아야 한다.

예를 들어 어떤 함수의 인자를 모든 caller가 항상 0으로 넘긴다고 하자. 언젠가 flexibility가 필요할지 모른다는 이유로 그 인자를 남겨 둘 수 있다. 그러나 실제로 사용될 때까지 한 번도 실행되지 않은 구현은 눈에 띄지 않은 채 망가졌을 가능성이 크다. 또는 훗날 요구되는 flexibility의 형태가 처음 예상과 전혀 다를 수 있다. Kernel 개발자는 사용되지 않는 인자를 제거하는 patch를 흔히 제출하므로, 일반적으로 그런 인자는 처음부터 추가하지 않는 것이 맞다.

Hardware 접근을 감추는 abstraction layer, 특히 driver 대부분을 여러 operating system에서 공용으로 사용하려고 만든 계층은 좋지 않게 평가된다. 이런 계층은 code의 실제 동작을 가리고 performance penalty까지 만들 수 있으므로 Linux kernel에 들어갈 자리가 아니다.

반대로 다른 kernel subsystem에서 상당한 양의 code를 복사하고 있다면, 공통 부분을 별도 library로 분리하거나 더 높은 계층에서 기능을 제공하는 것이 맞는지 검토해야 한다. 동일한 code를 kernel 곳곳에 반복해서 복제하는 데에는 가치가 없다.

#ifdef와 C preprocessor

108-132

C preprocessor는 하나의 source file에 많은 flexibility를 효율적으로 넣는 수단처럼 보이기 때문에 일부 C programmer에게 강한 유혹이 된다. 하지만 preprocessor는 C 언어 자체가 아니다. 과도하게 사용하면 다른 사람이 읽기 어려워지고 compiler가 correctness를 검사하기도 어려워진다. Preprocessor 사용량이 지나치다면 code 정리가 필요하다는 신호인 경우가 거의 대부분이다.

#ifdef에 의한 conditional compilation은 강력하고 kernel 내부에서도 사용된다. 그렇다고 source 곳곳을 #ifdef block으로 채워서는 안 된다. 가능하면 #ifdef는 header file 안으로 제한한다. 조건에 따라 빠져야 하는 구현은, 해당 기능이 없을 때 빈 함수가 되는 작은 function으로 감쌀 수 있다. Compiler는 빈 함수 call을 제거하므로 결과 code는 더 깔끔하고 흐름도 따라가기 쉽다.

/* 조건부 구현은 header의 stub으로 격리하는 형태가 바람직하다. */
#ifdef CONFIG_FEATURE
void feature_run(struct device *dev);
#else
static inline void feature_run(struct device *dev)
{
}
#endif

위 code는 원문의 설명을 구체화한 예시이며 Linux v6.18.37 원문에 직접 포함된 snippet은 아니다.

C preprocessor macro에는 side effect를 가진 expression을 여러 번 평가할 수 있다는 위험과 type safety가 없다는 문제가 있다. Macro를 만들고 싶다면 먼저 inline function으로 바꿀 수 있는지 검토한다. 생성되는 machine code는 같을 수 있지만 inline function은 읽기 쉽고 인자를 중복 평가하지 않으며 compiler가 인자와 반환값의 type을 검사할 수 있다.

Inline function과 cache 비용

135-157

Inline function에도 자체적인 위험이 있다. Function call을 없애면 효율적일 것이라는 생각에 source file을 inline function으로 가득 채우기 쉽지만, 오히려 performance가 떨어질 수 있다. Function body가 모든 call site에 복제되면서 compiled kernel 크기가 불어나고, processor cache에 압력을 주어 실행 속도가 크게 느려질 수 있기 때문이다.

일반적으로 inline function은 아주 작고 드물게 사용해야 한다. Function call 자체의 비용은 그렇게 크지 않다. 다수의 inline function을 만드는 것은 premature optimization의 전형적인 사례다.

Kernel programmer가 cache effect를 무시하면 큰 대가를 치를 수 있다. 입문 data structure 수업에서 말하는 전통적인 time/space tradeoff는 현대 hardware에 그대로 적용되지 않는 경우가 많다. 더 큰 program은 cache 효율이 나빠져 더 느리게 실행되므로, 이 환경에서는 공간이 곧 시간이다.

최근 compiler는 특정 함수를 실제로 inline할지 스스로 결정하는 데 더 적극적이다. 따라서 inline keyword를 널리 붙이는 일은 과도할 뿐 아니라 아무 효과도 없을 수 있다.

처음부터 concurrency와 locking을 설계한다

160-190

2006년 5월 Devicescape networking stack이 GPL로 공개되어 mainline kernel에 들어갈 수 있게 되었을 때 큰 기대를 받았다. 당시 Linux wireless networking 지원은 부족하다는 평가를 받았고 이 stack이 상황을 개선할 것으로 보였다. 그러나 실제 mainline merge는 2007년 6월, Linux 2.6.22에서야 이루어졌다.

이 code에는 회사 내부에서 비공개로 개발된 흔적이 여러 곳에 있었고, 특히 multiprocessor system에서 동작하도록 설계되지 않았다는 큰 문제가 있었다. 현재 mac80211이라고 부르는 이 networking stack은 merge 전에 locking 체계를 사후에 추가해야 했다.

예전에는 multiprocessor가 만드는 concurrency 문제를 고려하지 않고 Linux kernel code를 작성할 수 있었다. 하지만 이 문서가 처음 작성될 당시에도 dual-core laptop은 이미 일상적인 장치였다. Single-processor system에서도 responsiveness를 높이는 작업은 kernel 내부 concurrency 수준을 올린다. Locking을 생각하지 않고 kernel code를 작성할 수 있던 시대는 오래전에 끝났다.

둘 이상의 thread가 동시에 접근할 수 있는 모든 resource, 즉 data structure와 hardware register 등은 lock으로 보호해야 한다. 새 code는 처음부터 이 요구를 반영해 작성해야 한다. 구현이 끝난 뒤 locking을 덧붙이는 일은 훨씬 어렵다. Kernel 개발자는 제공되는 locking primitive를 충분히 이해하고 상황에 맞는 도구를 골라야 하며, concurrency를 제대로 고려하지 않은 code는 mainline 진입 과정에서 큰 어려움을 겪는다.

Regression과 user-space ABI

193-225

기존 사용자에게 동작하던 무언가를 깨뜨리는 대신 큰 개선을 얻는 변경을 시도하고 싶을 수 있다. 이런 변경을 regression이라고 하며 mainline kernel에서는 매우 강하게 거부된다. 극히 일부 예외를 제외하면 regression을 제때 고치지 못할 경우 해당 변경은 revert된다. 가장 좋은 방법은 처음부터 regression을 만들지 않는 것이다.

한 system을 깨뜨리는 대신 열 system에 새 기능을 제공한다면 regression을 정당화할 수 있다는 주장도 있다. 그러나 2007년 7월 Linus는 이 생각을 다음과 같이 설명했다.

So we don't fix bugs by introducing new problems.  That way lies
madness, and nobody ever knows if you actually make any real
progress at all. Is it two steps forwards, one step back, or one
step forward and two steps back?

즉, 새로운 문제를 도입하는 방식으로 bug를 고치지 않는다. 그렇게 하면 실제로 전진했는지조차 판단할 수 없다. 두 걸음 나아가고 한 걸음 물러난 것인지, 한 걸음 나아가고 두 걸음 물러난 것인지 알 수 없기 때문이다.

특히 허용되지 않는 regression은 user-space ABI를 바꾸는 일이다. Interface가 user space로 한번 export되면 사실상 영구히 지원해야 한다. 이 때문에 user-space interface 설계는 특히 어렵다. 호환되지 않는 방식으로 나중에 고칠 수 없으므로 처음부터 제대로 만들어야 하며, 충분한 검토와 명확한 문서, 넓은 범위의 review가 항상 필요하다.

Compiler warning과 runtime debugging 도구

228-304

오류 없는 code 작성은 아직 소수만이 도달할 수 있는 이상에 가깝다. 현실적인 목표는 mainline에 들어가기 전에 가능한 한 많은 오류를 찾아 고치는 것이다. Kernel 개발자는 잘 드러나지 않는 다양한 문제를 자동으로 찾는 도구를 마련해 왔다. Computer가 미리 찾은 문제는 나중에 사용자가 겪지 않아도 되는 문제이므로 가능한 모든 자동 검사 도구를 사용해야 한다.

첫 단계는 compiler warning을 무시하지 않는 것이다. 현대 gcc는 많은 잠재 오류를 찾아 경고할 수 있고, 그 경고는 실제 문제를 가리키는 경우가 많다. Review에 제출하는 code는 원칙적으로 compiler warning을 만들지 않아야 한다. Warning을 없앨 때는 근본 원인을 이해해야 하며, 원인을 해결하지 않은 채 메시지만 사라지게 하는 수정은 피한다.

make KCFLAGS=-W

기본값으로 활성화되지 않은 compiler warning까지 보려면 위와 같이 build한다. Kernel에는 debugging 기능을 켜는 configuration option도 많으며 대부분 kernel hacking submenu에 있다. 개발 또는 test용 kernel에서는 다음 option을 켜는 것이 좋다.

  • FRAME_WARN: 지정 크기보다 큰 stack frame을 경고한다. 출력이 많아질 수 있지만 kernel의 다른 영역에서 나온 경고까지 모두 직접 해결할 필요는 없다.
  • DEBUG_OBJECTS: kernel이 만드는 여러 object의 lifetime을 추적하고 operation 순서가 잘못되면 경고한다. 독자적인 복잡한 object를 생성하고 외부에 제공하는 subsystem을 추가한다면 object debugging infrastructure 지원도 고려한다.
  • DEBUG_SLAB: memory allocation과 사용 과정에서 발생하는 다양한 오류를 찾는다. 대부분의 development kernel에서 사용해야 한다.
  • DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP, DEBUG_MUTEXES: 흔한 locking 오류를 다수 찾아낸다.

그 밖에도 debugging option이 많이 있다. 일부는 performance overhead가 커서 항상 켜 둘 수 없지만, 어떤 option이 있는지 학습하는 데 들인 시간은 대개 짧은 기간 안에 여러 배로 돌아온다.

더 무거운 debugging 도구 중 하나가 locking checker인 lockdep이다. Lockdep은 system의 모든 spinlock과 mutex 획득·해제, lock 사이의 획득 순서, 현재 interrupt 환경 등을 추적한다. 이를 바탕으로 lock이 항상 같은 순서로 잡히는지, 모든 경로에서 interrupt에 대한 전제가 일치하는지 검사한다. 드물게 발생할 수 있는 deadlock 시나리오를 배포 전에 자동으로 찾을 수 있으므로, 단순하지 않은 locking을 포함한 code는 제출 전에 lockdep을 켜고 실행해야 한다.

신중한 kernel programmer라면 memory allocation처럼 실패할 수 있는 operation의 return status를 확인한다. 하지만 그 결과로 작성한 failure recovery path는 실제로 한 번도 실행해 보지 않았을 가능성이 높다. Test되지 않은 code는 망가진 code일 가능성이 크므로 error-handling path도 의도적으로 실행해 보아야 한다.

Kernel의 fault injection framework는 특히 memory allocation 실패를 주입해 이 검증을 수행한다. 활성화하면 설정한 비율의 allocation을 실패시킬 수 있고, 실패를 특정 code range로 제한할 수도 있다. Fault injection 상태로 실행하면 상황이 나빠졌을 때 code가 실제로 어떻게 반응하는지 볼 수 있다. 사용법은 Documentation/fault-injection/fault-injection.rst에 설명되어 있다.

Sparse, Coccinelle과 cross compilation

306-331

Sparse static analysis 도구는 user-space address와 kernel-space address의 혼동, big-endian 값과 little-endian 값의 혼합, bit flag 집합이 필요한 자리에 integer를 전달하는 문제 등을 찾아 경고한다. Distribution package에 없다면 https://sparse.wiki.kernel.org/index.php/Main_Page 에서 별도로 설치한 뒤 make 명령에 C=1을 추가하여 실행한다.

make C=1

Coccinelle은 다양한 잠재 coding 문제를 찾고 수정안까지 제안할 수 있다. Kernel tree의 scripts/coccinelle directory에는 여러 semantic patch가 포함되어 있으며 make coccicheck를 실행하면 이 patch들을 순회하면서 발견한 문제를 보고한다. 자세한 내용은 Documentation/dev-tools/coccinelle.rst를 참고한다.

make coccicheck

또 다른 종류의 portability 오류는 다른 architecture용으로 compile할 때 가장 잘 드러난다. S/390 system이나 Blackfin development board를 실제로 보유하지 않아도 cross compiler로 compilation 단계는 수행할 수 있다. x86 system용 cross compiler 모음은 https://www.kernel.org/pub/tools/crosstool/ 에 있다. 이를 설치하고 사용하는 데 시간을 들이면 나중에 곤란한 상황을 피할 수 있다.

Patch와 interface 문서화

334-389

Kernel 개발에서 documentation은 규칙이라기보다 예외였던 시기가 많았다. 그래도 충분한 문서는 새 code의 merge를 쉽게 하고 다른 개발자와 사용자의 작업을 돕는다. 이제는 문서 추가가 사실상 필수인 경우도 많다.

모든 patch의 첫 번째 documentation은 함께 제출하는 changelog다. Log entry에는 해결하려는 문제, 해결 방법의 형태, patch 작업에 참여한 사람, 관련 performance 영향, patch를 이해하는 데 필요한 기타 사항을 적어야 한다. 특히 그 patch를 적용할 가치가 왜 있는지 설명해야 한다. 놀랄 만큼 많은 개발자가 이 정보를 빠뜨린다.

새 sysfs 또는 /proc file을 포함하여 새로운 user-space interface를 추가하는 code에는 user-space 개발자가 interface 사용법과 의미를 알 수 있는 문서가 따라야 한다. 형식과 필수 정보는 Documentation/ABI/README에 설명되어 있다.

Documentation/admin-guide/kernel-parameters.rst는 kernel boot-time parameter 전체를 설명한다. 새 parameter를 추가하는 patch는 해당 문서에도 항목을 추가해야 한다. 새 configuration option에는 option의 의미와 사용자가 언제 선택해야 하는지를 명확히 설명하는 help text가 반드시 있어야 한다.

여러 subsystem의 internal API는 특별한 형식의 comment로 문서화되며 kernel-doc script가 이를 추출해 다양한 형식으로 만들 수 있다. Kerneldoc comment를 사용하는 subsystem에서 작업한다면 기존 comment를 함께 유지하고, 외부에 제공되는 function에는 필요에 따라 새 comment를 추가한다. 아직 이런 문서가 없는 영역에서도 미래를 위해 kerneldoc comment를 추가해 두는 것은 유용하며 초보 kernel 개발자가 시작하기 좋은 작업이기도 하다. Comment 형식과 kerneldoc template 생성법은 Documentation/doc-guide/에 있다.

기존 kernel code를 많이 읽다 보면 comment가 없는 경우가 흔하다는 것을 알 수 있다. 하지만 새 code에 대한 기대 수준은 과거보다 높아졌으므로 comment 없는 code는 merge하기 더 어렵다. 그렇다고 장황한 comment를 원하는 것은 아니다. Code 자체가 읽을 수 있어야 하고, comment는 미묘하거나 code만으로 드러나지 않는 부분을 설명해야 한다.

  • Memory barrier를 사용한 곳에는 그 barrier가 왜 필요한지 설명하는 한 줄을 둔다.
  • Data structure의 locking rule은 적절한 위치에 설명한다.
  • 핵심 data structure에는 전체 역할과 불변 조건을 포함한 충분한 문서를 둔다.
  • 서로 떨어진 code 조각 사이의 명확하지 않은 dependency를 밝혀 둔다.
  • 겉보기에는 불필요해 보여 잘못된 cleanup을 유도할 수 있는 구현에는 왜 그 방식이어야 하는지 적는다.

Internal API 변경의 책임

392-425

Kernel이 user space에 제공하는 binary interface는 극도로 심각한 상황이 아니면 깨뜨릴 수 없다. 반면 kernel internal programming interface는 매우 유동적이며 필요할 때 변경할 수 있다. Kernel API를 피해 우회 구현을 하고 있거나 필요한 기능이 없어 특정 API를 사용하지 못한다면, API 자체를 바꿔야 한다는 신호일 수 있다. Kernel 개발자는 그런 변경을 할 권한이 있다.

물론 조건이 있다. API 변경에는 충분한 근거가 필요하다. Internal API를 바꾸는 patch에는 무엇을 어떻게 바꾸며 왜 필요한지 설명을 붙여야 한다. 또한 더 큰 patch 안에 묻어 두지 말고 API 변경을 독립된 patch로 분리해야 한다.

Internal API를 바꾼 개발자는 일반적으로 그 변경으로 인해 kernel tree 안에서 깨지는 모든 code를 고칠 책임도 진다. 널리 사용되는 function이라면 수백 또는 수천 곳을 수정해야 할 수 있고, 그중 다수는 다른 개발자가 진행 중인 작업과 충돌할 가능성이 있다. 매우 큰 작업이 될 수 있으므로 변경 근거가 확실한지 먼저 확인해야 한다. 범위가 넓은 API 변경에는 Coccinelle이 도움을 줄 수 있다.

호환되지 않는 API 변경을 할 때는 가능하면 아직 갱신되지 않은 code가 compiler에 의해 검출되도록 설계한다. 그러면 tree 안의 모든 사용처를 찾았는지 확인할 수 있고, out-of-tree code 개발자도 대응해야 할 변경이 생겼음을 알 수 있다. Kernel 개발자가 out-of-tree code 지원을 책임질 필요는 없지만, 필요 이상으로 그들의 작업을 어렵게 만들 이유도 없다.