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

Linux 6.18.37 · Core API

Linked Lists in Linux

Linux circular doubly linked list의 선언, 추가, 순회, 삭제, 절단, 이동, 회전, 교환, splice와 concurrency 규칙을 예제로 설명합니다.

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

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

1. 요약·해설

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

요약과 해설

list.rst:1-776

Linux list API는 payload structure 안에 `struct list_head`를 embedded하고 `container_of()`로 원래 object를 찾는 intrusive circular doubly linked list입니다. 이 방식은 payload type과 무관한 generic operation을 가능하게 하지만 cache locality가 나쁘므로 성능이 중요한 곳에서는 다른 structure도 검토해야 합니다.

`list_add()`와 `list_add_tail()`은 head 또는 tail에 삽입하고, `list_for_each_entry()`는 payload type으로 순회합니다. 삭제 중 순회에는 `_safe` variant를 사용하며 `list_del()` 뒤 node는 poisoned되고 `list_del_init()` 뒤에는 self-linked 상태로 재초기화됩니다.

절단, 이동, 회전, 교환과 splice helper는 pointer를 빠르게 재연결하지만 membership을 검증하지 않는 API도 있습니다. 특히 `list_splice()` 뒤 donor head는 유효한 독립 list가 아니므로 다시 사용할 때는 `list_splice_init()`을 선택해야 하며 concurrent access는 lock 또는 RCU로 보호해야 합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0+
2
3 =====================
4 Linked Lists in Linux
5 =====================
6
7 :Author: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
8
9 .. contents::
10
11 Introduction
12 ============
13
14 Linked lists are one of the most basic data structures used in many programs.
15 The Linux kernel implements several different flavours of linked lists. The
16 purpose of this document is not to explain linked lists in general, but to show
17 new kernel developers how to use the Linux kernel implementations of linked
18 lists.
19
20 Please note that while linked lists certainly are ubiquitous, they are rarely
21 the best data structure to use in cases where a simple array doesn't already
22 suffice. In particular, due to their poor data locality, linked lists are a bad
23 choice in situations where performance may be of consideration. Familiarizing
24 oneself with other in-kernel generic data structures, especially for concurrent
25 accesses, is highly encouraged.
26
27 Linux implementation of doubly linked lists
28 ===========================================
29
30 Linux's linked list implementations can be used by including the header file
31 ``<linux/list.h>``.
32
33 The doubly-linked list will likely be the most familiar to many readers. It's a
34 list that can efficiently be traversed forwards and backwards.
35
36 The Linux kernel's doubly-linked list is circular in nature. This means that to
37 get from the head node to the tail, we can just travel one edge backwards.
38 Similarly, to get from the tail node to the head, we can simply travel forwards
39 "beyond" the tail and arrive back at the head.
40
41 Declaring a node
42 ----------------
43
44 A node in a doubly-linked list is declared by adding a struct list_head
45 member to the data structure you wish to be contained in the list:
46
47 .. code-block:: c
48
49 struct clown {
50 unsigned long long shoe_size;
51 const char *name;
52 struct list_head node; /* the aforementioned member */
53 };
54
55 This may be an unfamiliar approach to some, as the classical explanation of a
56 linked list is a list node data structure with pointers to the previous and next
57 list node, as well the payload data. Linux chooses this approach because it
58 allows for generic list modification code regardless of what data structure is
59 contained within the list. Since the struct list_head member is not a pointer
60 but part of the data structure proper, the container_of() pattern can be used by
61 the list implementation to access the payload data regardless of its type, while
62 staying oblivious to what said type actually is.
63
64 Declaring and initializing a list
65 ---------------------------------
66
67 A doubly-linked list can then be declared as just another struct list_head,
68 and initialized with the LIST_HEAD_INIT() macro during initial assignment, or
69 with the INIT_LIST_HEAD() function later:
70
71 .. code-block:: c
72
73 struct clown_car {
74 int tyre_pressure[4];
75 struct list_head clowns; /* Looks like a node! */
76 };
77
78 /* ... Somewhere later in our driver ... */
79
80 static int circus_init(struct circus_priv *circus)
81 {
82 struct clown_car other_car = {
83 .tyre_pressure = {10, 12, 11, 9},
84 .clowns = LIST_HEAD_INIT(other_car.clowns)
85 };
86
87 INIT_LIST_HEAD(&circus->car.clowns);
88
89 return 0;
90 }
91
92 A further point of confusion to some may be that the list itself doesn't really
93 have its own type. The concept of the entire linked list and a
94 struct list_head member that points to other entries in the list are one and
95 the same.
96
97 Adding nodes to the list
98 ------------------------
99
100 Adding a node to the linked list is done through the list_add() macro.
101
102 We'll return to our clown car example to illustrate how nodes get added to the
103 list:
104
105 .. code-block:: c
106
107 static int circus_fill_car(struct circus_priv *circus)
108 {
109 struct clown_car *car = &circus->car;
110 struct clown *grock;
111 struct clown *dimitri;
112
113 /* State 1 */
114
115 grock = kzalloc(sizeof(*grock), GFP_KERNEL);
116 if (!grock)
117 return -ENOMEM;
118 grock->name = "Grock";
119 grock->shoe_size = 1000;
120
121 /* Note that we're adding the "node" member */
122 list_add(&grock->node, &car->clowns);
123
124 /* State 2 */
125
126 dimitri = kzalloc(sizeof(*dimitri), GFP_KERNEL);
127 if (!dimitri)
128 return -ENOMEM;
129 dimitri->name = "Dimitri";
130 dimitri->shoe_size = 50;
131
132 list_add(&dimitri->node, &car->clowns);
133
134 /* State 3 */
135
136 return 0;
137 }
138
139 In State 1, our list of clowns is still empty::
140
141 .------.
142 v |
143 .--------. |
144 | clowns |--'
145 '--------'
146
147 This diagram shows the singular "clowns" node pointing at itself. In this
148 diagram, and all following diagrams, only the forward edges are shown, to aid in
149 clarity.
150
151 In State 2, we've added Grock after the list head::
152
153 .--------------------.
154 v |
155 .--------. .-------. |
156 | clowns |---->| Grock |--'
157 '--------' '-------'
158
159 This diagram shows the "clowns" node pointing at a new node labeled "Grock".
160 The Grock node is pointing back at the "clowns" node.
161
162 In State 3, we've added Dimitri after the list head, resulting in the following::
163
164 .------------------------------------.
165 v |
166 .--------. .---------. .-------. |
167 | clowns |---->| Dimitri |---->| Grock |--'
168 '--------' '---------' '-------'
169
170 This diagram shows the "clowns" node pointing at a new node labeled "Dimitri",
171 which then points at the node labeled "Grock". The "Grock" node still points
172 back at the "clowns" node.
173
174 If we wanted to have Dimitri inserted at the end of the list instead, we'd use
175 list_add_tail(). Our code would then look like this:
176
177 .. code-block:: c
178
179 static int circus_fill_car(struct circus_priv *circus)
180 {
181 /* ... */
182
183 list_add_tail(&dimitri->node, &car->clowns);
184
185 /* State 3b */
186
187 return 0;
188 }
189
190 This results in the following list::
191
192 .------------------------------------.
193 v |
194 .--------. .-------. .---------. |
195 | clowns |---->| Grock |---->| Dimitri |--'
196 '--------' '-------' '---------'
197
198 This diagram shows the "clowns" node pointing at the node labeled "Grock",
199 which points at the new node labeled "Dimitri". The node labeled "Dimitri"
200 points back at the "clowns" node.
201
202 Traversing the list
203 -------------------
204
205 To iterate the list, we can loop through all nodes within the list with
206 list_for_each().
207
208 In our clown example, this results in the following somewhat awkward code:
209
210 .. code-block:: c
211
212 static unsigned long long circus_get_max_shoe_size(struct circus_priv *circus)
213 {
214 unsigned long long res = 0;
215 struct clown *e;
216 struct list_head *cur;
217
218 list_for_each(cur, &circus->car.clowns) {
219 e = list_entry(cur, struct clown, node);
220 if (e->shoe_size > res)
221 res = e->shoe_size;
222 }
223
224 return res;
225 }
226
227 The list_entry() macro internally uses the aforementioned container_of() to
228 retrieve the data structure instance that ``node`` is a member of.
229
230 Note how the additional list_entry() call is a little awkward here. It's only
231 there because we're iterating through the ``node`` members, but we really want
232 to iterate through the payload, i.e. the ``struct clown`` that contains each
233 node's struct list_head. For this reason, there is a second macro:
234 list_for_each_entry()
235
236 Using it would change our code to something like this:
237
238 .. code-block:: c
239
240 static unsigned long long circus_get_max_shoe_size(struct circus_priv *circus)
241 {
242 unsigned long long res = 0;
243 struct clown *e;
244
245 list_for_each_entry(e, &circus->car.clowns, node) {
246 if (e->shoe_size > res)
247 res = e->shoe_size;
248 }
249
250 return res;
251 }
252
253 This eliminates the need for the list_entry() step, and our loop cursor is now
254 of the type of our payload. The macro is given the member name that corresponds
255 to the list's struct list_head within the clown data structure so that it can
256 still walk the list.
257
258 Removing nodes from the list
259 ----------------------------
260
261 The list_del() function can be used to remove entries from the list. It not only
262 removes the given entry from the list, but poisons the entry's ``prev`` and
263 ``next`` pointers, so that unintended use of the entry after removal does not
264 go unnoticed.
265
266 We can extend our previous example to remove one of the entries:
267
268 .. code-block:: c
269
270 static int circus_fill_car(struct circus_priv *circus)
271 {
272 /* ... */
273
274 list_add(&dimitri->node, &car->clowns);
275
276 /* State 3 */
277
278 list_del(&dimitri->node);
279
280 /* State 4 */
281
282 return 0;
283 }
284
285 The result of this would be this::
286
287 .--------------------.
288 v |
289 .--------. .-------. | .---------.
290 | clowns |---->| Grock |--' | Dimitri |
291 '--------' '-------' '---------'
292
293 This diagram shows the "clowns" node pointing at the node labeled "Grock",
294 which points back at the "clowns" node. Off to the side is a lone node labeled
295 "Dimitri", which has no arrows pointing anywhere.
296
297 Note how the Dimitri node does not point to itself; its pointers are
298 intentionally set to a "poison" value that the list code refuses to traverse.
299
300 If we wanted to reinitialize the removed node instead to make it point at itself
301 again like an empty list head, we can use list_del_init() instead:
302
303 .. code-block:: c
304
305 static int circus_fill_car(struct circus_priv *circus)
306 {
307 /* ... */
308
309 list_add(&dimitri->node, &car->clowns);
310
311 /* State 3 */
312
313 list_del_init(&dimitri->node);
314
315 /* State 4b */
316
317 return 0;
318 }
319
320 This results in the deleted node pointing to itself again::
321
322 .--------------------. .-------.
323 v | v |
324 .--------. .-------. | .---------. |
325 | clowns |---->| Grock |--' | Dimitri |--'
326 '--------' '-------' '---------'
327
328 This diagram shows the "clowns" node pointing at the node labeled "Grock",
329 which points back at the "clowns" node. Off to the side is a lone node labeled
330 "Dimitri", which points to itself.
331
332 Traversing whilst removing nodes
333 --------------------------------
334
335 Deleting entries while we're traversing the list will cause problems if we use
336 list_for_each() and list_for_each_entry(), as deleting the current entry would
337 modify the ``next`` pointer of it, which means the traversal can't properly
338 advance to the next list entry.
339
340 There is a solution to this however: list_for_each_safe() and
341 list_for_each_entry_safe(). These take an additional parameter of a pointer to
342 a struct list_head to use as temporary storage for the next entry during
343 iteration, solving the issue.
344
345 An example of how to use it:
346
347 .. code-block:: c
348
349 static void circus_eject_insufficient_clowns(struct circus_priv *circus)
350 {
351 struct clown *e;
352 struct clown *n; /* temporary storage for safe iteration */
353
354 list_for_each_entry_safe(e, n, &circus->car.clowns, node) {
355 if (e->shoe_size < 500)
356 list_del(&e->node);
357 }
358 }
359
360 Proper memory management (i.e. freeing the deleted node while making sure
361 nothing still references it) in this case is left as an exercise to the reader.
362
363 Cutting a list
364 --------------
365
366 There are two helper functions to cut lists with. Both take elements from the
367 list ``head``, and replace the contents of the list ``list``.
368
369 The first such function is list_cut_position(). It removes all list entries from
370 ``head`` up to and including ``entry``, placing them in ``list`` instead.
371
372 In this example, it's assumed we start with the following list::
373
374 .----------------------------------------------------------------.
375 v |
376 .--------. .-------. .---------. .-----. .---------. |
377 | clowns |---->| Grock |---->| Dimitri |---->| Pic |---->| Alfredo |--'
378 '--------' '-------' '---------' '-----' '---------'
379
380 With the following code, every clown up to and including "Pic" is moved from
381 the "clowns" list head to a separate struct list_head initialized at local
382 stack variable ``retirement``:
383
384 .. code-block:: c
385
386 static void circus_retire_clowns(struct circus_priv *circus)
387 {
388 struct list_head retirement = LIST_HEAD_INIT(retirement);
389 struct clown *grock, *dimitri, *pic, *alfredo;
390 struct clown_car *car = &circus->car;
391
392 /* ... clown initialization, list adding ... */
393
394 list_cut_position(&retirement, &car->clowns, &pic->node);
395
396 /* State 1 */
397 }
398
399 The resulting ``car->clowns`` list would be this::
400
401 .----------------------.
402 v |
403 .--------. .---------. |
404 | clowns |---->| Alfredo |--'
405 '--------' '---------'
406
407 Meanwhile, the ``retirement`` list is transformed to the following::
408
409 .--------------------------------------------------.
410 v |
411 .------------. .-------. .---------. .-----. |
412 | retirement |---->| Grock |---->| Dimitri |---->| Pic |--'
413 '------------' '-------' '---------' '-----'
414
415 The second function, list_cut_before(), is much the same, except it cuts before
416 the ``entry`` node, i.e. it removes all list entries from ``head`` up to but
417 excluding ``entry``, placing them in ``list`` instead. This example assumes the
418 same initial starting list as the previous example:
419
420 .. code-block:: c
421
422 static void circus_retire_clowns(struct circus_priv *circus)
423 {
424 struct list_head retirement = LIST_HEAD_INIT(retirement);
425 struct clown *grock, *dimitri, *pic, *alfredo;
426 struct clown_car *car = &circus->car;
427
428 /* ... clown initialization, list adding ... */
429
430 list_cut_before(&retirement, &car->clowns, &pic->node);
431
432 /* State 1b */
433 }
434
435 The resulting ``car->clowns`` list would be this::
436
437 .----------------------------------.
438 v |
439 .--------. .-----. .---------. |
440 | clowns |---->| Pic |---->| Alfredo |--'
441 '--------' '-----' '---------'
442
443 Meanwhile, the ``retirement`` list is transformed to the following::
444
445 .--------------------------------------.
446 v |
447 .------------. .-------. .---------. |
448 | retirement |---->| Grock |---->| Dimitri |--'
449 '------------' '-------' '---------'
450
451 It should be noted that both functions will destroy links to any existing nodes
452 in the destination ``struct list_head *list``.
453
454 Moving entries and partial lists
455 --------------------------------
456
457 The list_move() and list_move_tail() functions can be used to move an entry
458 from one list to another, to either the start or end respectively.
459
460 In the following example, we'll assume we start with two lists ("clowns" and
461 "sidewalk" in the following initial state "State 0"::
462
463 .----------------------------------------------------------------.
464 v |
465 .--------. .-------. .---------. .-----. .---------. |
466 | clowns |---->| Grock |---->| Dimitri |---->| Pic |---->| Alfredo |--'
467 '--------' '-------' '---------' '-----' '---------'
468
469 .-------------------.
470 v |
471 .----------. .-----. |
472 | sidewalk |---->| Pio |--'
473 '----------' '-----'
474
475 We apply the following example code to the two lists:
476
477 .. code-block:: c
478
479 static void circus_clowns_exit_car(struct circus_priv *circus)
480 {
481 struct list_head sidewalk = LIST_HEAD_INIT(sidewalk);
482 struct clown *grock, *dimitri, *pic, *alfredo, *pio;
483 struct clown_car *car = &circus->car;
484
485 /* ... clown initialization, list adding ... */
486
487 /* State 0 */
488
489 list_move(&pic->node, &sidewalk);
490
491 /* State 1 */
492
493 list_move_tail(&dimitri->node, &sidewalk);
494
495 /* State 2 */
496 }
497
498 In State 1, we arrive at the following situation::
499
500 .-----------------------------------------------------.
501 | |
502 v |
503 .--------. .-------. .---------. .---------. |
504 | clowns |---->| Grock |---->| Dimitri |---->| Alfredo |--'
505 '--------' '-------' '---------' '---------'
506
507 .-------------------------------.
508 v |
509 .----------. .-----. .-----. |
510 | sidewalk |---->| Pic |---->| Pio |--'
511 '----------' '-----' '-----'
512
513 In State 2, after we've moved Dimitri to the tail of sidewalk, the situation
514 changes as follows::
515
516 .-------------------------------------.
517 | |
518 v |
519 .--------. .-------. .---------. |
520 | clowns |---->| Grock |---->| Alfredo |--'
521 '--------' '-------' '---------'
522
523 .-----------------------------------------------.
524 v |
525 .----------. .-----. .-----. .---------. |
526 | sidewalk |---->| Pic |---->| Pio |---->| Dimitri |--'
527 '----------' '-----' '-----' '---------'
528
529 As long as the source and destination list head are part of the same list, we
530 can also efficiently bulk move a segment of the list to the tail end of the
531 list. We continue the previous example by adding a list_bulk_move_tail() after
532 State 2, moving Pic and Pio to the tail end of the sidewalk list.
533
534 .. code-block:: c
535
536 static void circus_clowns_exit_car(struct circus_priv *circus)
537 {
538 struct list_head sidewalk = LIST_HEAD_INIT(sidewalk);
539 struct clown *grock, *dimitri, *pic, *alfredo, *pio;
540 struct clown_car *car = &circus->car;
541
542 /* ... clown initialization, list adding ... */
543
544 /* State 0 */
545
546 list_move(&pic->node, &sidewalk);
547
548 /* State 1 */
549
550 list_move_tail(&dimitri->node, &sidewalk);
551
552 /* State 2 */
553
554 list_bulk_move_tail(&sidewalk, &pic->node, &pio->node);
555
556 /* State 3 */
557 }
558
559 For the sake of brevity, only the altered "sidewalk" list at State 3 is depicted
560 in the following diagram::
561
562 .-----------------------------------------------.
563 v |
564 .----------. .---------. .-----. .-----. |
565 | sidewalk |---->| Dimitri |---->| Pic |---->| Pio |--'
566 '----------' '---------' '-----' '-----'
567
568 Do note that list_bulk_move_tail() does not do any checking as to whether all
569 three supplied ``struct list_head *`` parameters really do belong to the same
570 list. If you use it outside the constraints the documentation gives, then the
571 result is a matter between you and the implementation.
572
573 Rotating entries
574 ----------------
575
576 A common write operation on lists, especially when using them as queues, is
577 to rotate it. A list rotation means entries at the front are sent to the back.
578
579 For rotation, Linux provides us with two functions: list_rotate_left() and
580 list_rotate_to_front(). The former can be pictured like a bicycle chain, taking
581 the entry after the supplied ``struct list_head *`` and moving it to the tail,
582 which in essence means the entire list, due to its circular nature, rotates by
583 one position.
584
585 The latter, list_rotate_to_front(), takes the same concept one step further:
586 instead of advancing the list by one entry, it advances it *until* the specified
587 entry is the new front.
588
589 In the following example, our starting state, State 0, is the following::
590
591 .-----------------------------------------------------------------.
592 v |
593 .--------. .-------. .---------. .-----. .---------. .-----. |
594 | clowns |-->| Grock |-->| Dimitri |-->| Pic |-->| Alfredo |-->| Pio |-'
595 '--------' '-------' '---------' '-----' '---------' '-----'
596
597 The example code being used to demonstrate list rotations is the following:
598
599 .. code-block:: c
600
601 static void circus_clowns_rotate(struct circus_priv *circus)
602 {
603 struct clown *grock, *dimitri, *pic, *alfredo, *pio;
604 struct clown_car *car = &circus->car;
605
606 /* ... clown initialization, list adding ... */
607
608 /* State 0 */
609
610 list_rotate_left(&car->clowns);
611
612 /* State 1 */
613
614 list_rotate_to_front(&alfredo->node, &car->clowns);
615
616 /* State 2 */
617
618 }
619
620 In State 1, we arrive at the following situation::
621
622 .-----------------------------------------------------------------.
623 v |
624 .--------. .---------. .-----. .---------. .-----. .-------. |
625 | clowns |-->| Dimitri |-->| Pic |-->| Alfredo |-->| Pio |-->| Grock |-'
626 '--------' '---------' '-----' '---------' '-----' '-------'
627
628 Next, after the list_rotate_to_front() call, we arrive in the following
629 State 2::
630
631 .-----------------------------------------------------------------.
632 v |
633 .--------. .---------. .-----. .-------. .---------. .-----. |
634 | clowns |-->| Alfredo |-->| Pio |-->| Grock |-->| Dimitri |-->| Pic |-'
635 '--------' '---------' '-----' '-------' '---------' '-----'
636
637 As is hopefully evident from the diagrams, the entries in front of "Alfredo"
638 were cycled to the tail end of the list.
639
640 Swapping entries
641 ----------------
642
643 Another common operation is that two entries need to be swapped with each other.
644
645 For this, Linux provides us with list_swap().
646
647 In the following example, we have a list with three entries, and swap two of
648 them. This is our starting state in "State 0"::
649
650 .-----------------------------------------.
651 v |
652 .--------. .-------. .---------. .-----. |
653 | clowns |-->| Grock |-->| Dimitri |-->| Pic |-'
654 '--------' '-------' '---------' '-----'
655
656 .. code-block:: c
657
658 static void circus_clowns_swap(struct circus_priv *circus)
659 {
660 struct clown *grock, *dimitri, *pic;
661 struct clown_car *car = &circus->car;
662
663 /* ... clown initialization, list adding ... */
664
665 /* State 0 */
666
667 list_swap(&dimitri->node, &pic->node);
668
669 /* State 1 */
670 }
671
672 The resulting list at State 1 is the following::
673
674 .-----------------------------------------.
675 v |
676 .--------. .-------. .-----. .---------. |
677 | clowns |-->| Grock |-->| Pic |-->| Dimitri |-'
678 '--------' '-------' '-----' '---------'
679
680 As is evident by comparing the diagrams, the "Pic" and "Dimitri" nodes have
681 traded places.
682
683 Splicing two lists together
684 ---------------------------
685
686 Say we have two lists, in the following example one represented by a list head
687 we call "knie" and one we call "stey". In a hypothetical circus acquisition,
688 the two list of clowns should be spliced together. The following is our
689 situation in "State 0"::
690
691 .-----------------------------------------.
692 | |
693 v |
694 .------. .-------. .---------. .-----. |
695 | knie |-->| Grock |-->| Dimitri |-->| Pic |--'
696 '------' '-------' '---------' '-----'
697
698 .-----------------------------.
699 v |
700 .------. .---------. .-----. |
701 | stey |-->| Alfredo |-->| Pio |--'
702 '------' '---------' '-----'
703
704 The function to splice these two lists together is list_splice(). Our example
705 code is as follows:
706
707 .. code-block:: c
708
709 static void circus_clowns_splice(void)
710 {
711 struct clown *grock, *dimitri, *pic, *alfredo, *pio;
712 struct list_head knie = LIST_HEAD_INIT(knie);
713 struct list_head stey = LIST_HEAD_INIT(stey);
714
715 /* ... Clown allocation and initialization here ... */
716
717 list_add_tail(&grock->node, &knie);
718 list_add_tail(&dimitri->node, &knie);
719 list_add_tail(&pic->node, &knie);
720 list_add_tail(&alfredo->node, &stey);
721 list_add_tail(&pio->node, &stey);
722
723 /* State 0 */
724
725 list_splice(&stey, &dimitri->node);
726
727 /* State 1 */
728 }
729
730 The list_splice() call here adds all the entries in ``stey`` to the list
731 ``dimitri``'s ``node`` list_head is in, after the ``node`` of ``dimitri``. A
732 somewhat surprising diagram of the resulting "State 1" follows::
733
734 .-----------------------------------------------------------------.
735 | |
736 v |
737 .------. .-------. .---------. .---------. .-----. .-----. |
738 | knie |-->| Grock |-->| Dimitri |-->| Alfredo |-->| Pio |-->| Pic |--'
739 '------' '-------' '---------' '---------' '-----' '-----'
740 ^
741 .-------------------------------'
742 |
743 .------. |
744 | stey |--'
745 '------'
746
747 Traversing the ``stey`` list no longer results in correct behavior. A call of
748 list_for_each() on ``stey`` results in an infinite loop, as it never returns
749 back to the ``stey`` list head.
750
751 This is because list_splice() did not reinitialize the list_head it took
752 entries from, leaving its pointer pointing into what is now a different list.
753
754 If we want to avoid this situation, list_splice_init() can be used. It does the
755 same thing as list_splice(), except reinitalizes the donor list_head after the
756 transplant.
757
758 Concurrency considerations
759 --------------------------
760
761 Concurrent access and modification of a list needs to be protected with a lock
762 in most cases. Alternatively and preferably, one may use the RCU primitives for
763 lists in read-mostly use-cases, where read accesses to the list are common but
764 modifications to the list less so. See Documentation/RCU/listRCU.rst for more
765 details.
766
767 Further reading
768 ---------------
769
770 * `How does the kernel implements Linked Lists? - KernelNewbies <https://kernelnewbies.org/FAQ/LinkedLists>`_
771
772 Full List API
773 =============
774
775 .. kernel-doc:: include/linux/list.h
776 :internal:
777

3. 한국어 전문 번역

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

Linux linked list 소개

1-26

SPDX 라이선스 식별자: GPL-2.0+

Linux의 linked list (Linked Lists in Linux)

저자: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>

이 페이지에는 contents directive가 있습니다.

Linked list는 많은 program에서 사용하는 가장 기본적인 data structure 중 하나입니다. Linux kernel은 여러 종류의 linked list를 구현합니다. 이 문서는 linked list 일반 이론이 아니라 새 kernel developer가 Linux kernel 구현을 사용하는 방법을 설명합니다.

Linked list가 널리 쓰이기는 하지만 단순한 array로 충분하지 않은 경우에도 최선의 data structure인 때는 드뭅니다. 특히 data locality가 좋지 않으므로 performance가 중요할 때는 나쁜 선택입니다. Concurrent access가 관련된 경우를 포함해 kernel의 다른 generic data structure도 익히기를 적극 권장합니다.

Linux doubly linked list

27-40

Linux의 doubly linked list 구현

Linux linked list 구현은 `<linux/list.h>` header file을 include하여 사용할 수 있습니다.

Doubly-linked list는 앞뒤 방향으로 효율적으로 순회할 수 있는 익숙한 형태입니다. Linux kernel의 doubly-linked list는 circular 구조이므로 head node에서 edge 하나를 뒤로 이동하면 tail에 닿고, tail에서 앞으로 더 이동하면 head로 돌아옵니다.

node 선언

41-63

Doubly-linked list의 node는 list에 포함할 data structure에 `struct list_head` member를 추가하여 선언합니다.

.. code-block:: c

  struct clown {
          unsigned long long shoe_size;
          const char *name;
          struct list_head node;  /* the aforementioned member */
  };

전통적인 설명은 previous/next node pointer와 payload를 한 list node structure에 두지만 Linux는 payload structure 안에 `struct list_head`를 embedded합니다. 이 방식은 list에 담긴 data type과 무관하게 generic modification code를 사용할 수 있게 합니다.

`struct list_head` member는 pointer가 아니라 structure 자체의 일부이므로 list 구현은 `container_of()` pattern으로 실제 type을 몰라도 payload data에 접근할 수 있습니다.

list 선언과 초기화

64-96

Doubly-linked list 자체도 `struct list_head`로 선언합니다. 최초 assignment에서는 `LIST_HEAD_INIT()` macro로, 이후에는 `INIT_LIST_HEAD()` function으로 초기화합니다.

.. code-block:: c

  struct clown_car {
          int tyre_pressure[4];
          struct list_head clowns;        /* Looks like a node! */
  };

  /* ... Somewhere later in our driver ... */

  static int circus_init(struct circus_priv *circus)
  {
          struct clown_car other_car = {
                .tyre_pressure = {10, 12, 11, 9},
                .clowns = LIST_HEAD_INIT(other_car.clowns)
          };

          INIT_LIST_HEAD(&circus->car.clowns);

          return 0;
  }

List 자체에 별도의 type이 없다는 점이 혼동될 수 있습니다. 전체 linked list라는 개념과 다른 entry를 가리키는 `struct list_head` member는 같은 표현을 사용합니다.

head 뒤에 node 추가

97-173

Linked list에 node를 추가할 때는 `list_add()` macro를 사용합니다. 다음 clown car 예제는 Grock과 Dimitri를 차례로 list head 뒤에 넣습니다.

.. code-block:: c

  static int circus_fill_car(struct circus_priv *circus)
  {
          struct clown_car *car = &circus->car;
          struct clown *grock;
          struct clown *dimitri;

          /* State 1 */

          grock = kzalloc(sizeof(*grock), GFP_KERNEL);
          if (!grock)
                  return -ENOMEM;
          grock->name = "Grock";
          grock->shoe_size = 1000;

          /* Note that we're adding the "node" member */
          list_add(&grock->node, &car->clowns);

          /* State 2 */

          dimitri = kzalloc(sizeof(*dimitri), GFP_KERNEL);
          if (!dimitri)
                  return -ENOMEM;
          dimitri->name = "Dimitri";
          dimitri->shoe_size = 50;

          list_add(&dimitri->node, &car->clowns);

          /* State 3 */

          return 0;
  }

State 1에서는 clown list가 비어 있고 head가 자신을 가리킵니다.

State 1: 빈 circular list
clowns

원문의 forward edge만 표시한 그림을 구조화했습니다.

State 2에서는 list head 바로 뒤에 Grock을 추가했습니다. Grock의 다음 edge는 다시 `clowns` head로 돌아갑니다.

State 2: Grock 추가
clownsGrock

새 node가 head 다음 위치에 들어갑니다.

State 3에서는 Dimitri를 다시 head 뒤에 추가했으므로 순서는 `clowns`, Dimitri, Grock이 됩니다.

State 3: Dimitri를 head 뒤에 추가
clownsDimitriGrock

최근 `list_add()`로 넣은 Dimitri가 첫 entry가 됩니다.

tail에 node 추가

174-201

Dimitri를 list 끝에 넣으려면 `list_add_tail()`을 사용합니다.

.. code-block:: c

  static int circus_fill_car(struct circus_priv *circus)
  {
          /* ... */

          list_add_tail(&dimitri->node, &car->clowns);

          /* State 3b */

          return 0;
  }

그 결과 Grock 뒤에 Dimitri가 오고 Dimitri의 다음 edge가 `clowns` head로 돌아갑니다.

State 3b: Dimitri를 tail에 추가
clownsGrockDimitri

`list_add_tail()`은 새 entry를 마지막 위치에 삽입합니다.

list 순회

202-257

`list_for_each()`로 list의 모든 node를 순회할 수 있습니다. 다만 cursor가 `struct list_head`이므로 payload를 얻기 위해 `list_entry()`를 호출해야 합니다.

.. code-block:: c

  static unsigned long long circus_get_max_shoe_size(struct circus_priv *circus)
  {
          unsigned long long res = 0;
          struct clown *e;
          struct list_head *cur;

          list_for_each(cur, &circus->car.clowns) {
                  e = list_entry(cur, struct clown, node);
                  if (e->shoe_size > res)
                          res = e->shoe_size;
          }

          return res;
  }

`list_entry()`는 내부에서 `container_of()`를 사용해 `node`가 속한 data structure instance를 찾습니다. 실제로 순회하려는 것은 node가 아니라 이를 포함하는 `struct clown` payload이므로 이 추가 변환은 다소 번거롭습니다.

`list_for_each_entry()`를 사용하면 payload type의 cursor로 직접 순회할 수 있습니다.

.. code-block:: c

  static unsigned long long circus_get_max_shoe_size(struct circus_priv *circus)
  {
          unsigned long long res = 0;
          struct clown *e;

          list_for_each_entry(e, &circus->car.clowns, node) {
                  if (e->shoe_size > res)
                          res = e->shoe_size;
          }

          return res;
  }

이 macro에는 clown structure 안에서 list의 `struct list_head`에 해당하는 member name을 전달하므로 `list_entry()` 단계 없이도 list를 이동할 수 있습니다.

node 제거와 재초기화

258-331

`list_del()`은 entry를 list에서 제거하고 `prev` 및 `next` pointer를 poison value로 바꿉니다. 따라서 제거한 entry를 의도치 않게 다시 사용하면 조용히 넘어가지 않습니다.

.. code-block:: c

  static int circus_fill_car(struct circus_priv *circus)
  {
          /* ... */

          list_add(&dimitri->node, &car->clowns);

          /* State 3 */

          list_del(&dimitri->node);

          /* State 4 */

          return 0;
  }

State 4에서 Grock만 list에 남고 Dimitri는 분리되어 어느 곳도 가리키지 않는 poisoned 상태입니다.

State 4: list_del() 뒤
clownsGrockclowns
Dimitridetached: poisoned prev/next

유효한 circular list와 분리된 poisoned node를 함께 나타냅니다.

제거한 node를 빈 list head처럼 다시 자신을 가리키게 하려면 `list_del_init()`을 사용합니다.

.. code-block:: c

  static int circus_fill_car(struct circus_priv *circus)
  {
          /* ... */

          list_add(&dimitri->node, &car->clowns);

          /* State 3 */

          list_del_init(&dimitri->node);

          /* State 4b */

          return 0;
  }

State 4b에서 Dimitri는 분리되어 있지만 self-loop로 재초기화되었습니다.

State 4b: list_del_init() 뒤
clownsGrock
Dimitri

기존 list와 self-linked Dimitri가 각각 독립된 circular list입니다.

제거하면서 안전하게 순회

332-362

`list_for_each()` 또는 `list_for_each_entry()`로 순회하면서 현재 entry를 삭제하면 `next` pointer가 바뀌어 다음 entry로 올바르게 이동할 수 없습니다.

`list_for_each_safe()`와 `list_for_each_entry_safe()`는 iteration 중 다음 entry를 임시 저장할 추가 `struct list_head` pointer를 받아 이 문제를 해결합니다.

.. code-block:: c

  static void circus_eject_insufficient_clowns(struct circus_priv *circus)
  {
          struct clown *e;
          struct clown *n;      /* temporary storage for safe iteration */

          list_for_each_entry_safe(e, n, &circus->car.clowns, node) {
                if (e->shoe_size < 500)
                        list_del(&e->node);
          }
  }

삭제한 node를 free하면서 다른 reference가 없는지 확인하는 올바른 memory management는 이 예제의 범위를 벗어납니다.

list 자르기

363-453

List를 자르는 helper는 두 가지이며 모두 `head` list에서 element를 떼어 `list` destination의 내용을 대체합니다.

`list_cut_position()`은 `head`부터 `entry`를 포함한 위치까지 제거해 `list`로 옮깁니다. 시작 상태는 다음과 같습니다.

자르기 전 초기 list
clownsGrockDimitriPicAlfredo

Grock부터 Alfredo까지 네 entry가 있는 circular list입니다.

다음 code는 Pic까지의 모든 clown을 local stack의 `retirement` list로 옮깁니다.

.. code-block:: c

  static void circus_retire_clowns(struct circus_priv *circus)
  {
          struct list_head retirement = LIST_HEAD_INIT(retirement);
          struct clown *grock, *dimitri, *pic, *alfredo;
          struct clown_car *car = &circus->car;

          /* ... clown initialization, list adding ... */

          list_cut_position(&retirement, &car->clowns, &pic->node);

          /* State 1 */
  }
list_cut_position() 뒤 원본
clownsAlfredo

`car->clowns`에는 Alfredo만 남습니다.

list_cut_position() 뒤 destination
retirementGrockDimitriPic

`retirement`에는 Grock, Dimitri, Pic이 순서대로 들어갑니다.

`list_cut_before()`는 `entry` 직전까지만 잘라 `entry`는 원본에 남깁니다. 같은 초기 상태에서 다음 code를 적용합니다.

.. code-block:: c

  static void circus_retire_clowns(struct circus_priv *circus)
  {
          struct list_head retirement = LIST_HEAD_INIT(retirement);
          struct clown *grock, *dimitri, *pic, *alfredo;
          struct clown_car *car = &circus->car;

          /* ... clown initialization, list adding ... */

          list_cut_before(&retirement, &car->clowns, &pic->node);

          /* State 1b */
  }
list_cut_before() 뒤 원본
clownsPicAlfredo

Pic과 Alfredo가 `car->clowns`에 남습니다.

list_cut_before() 뒤 destination
retirementGrockDimitri

Grock과 Dimitri만 `retirement`로 이동합니다.

두 함수 모두 destination `struct list_head *list`에 기존 node가 연결되어 있었다면 그 link를 파괴한다는 점에 주의해야 합니다.

entry와 부분 list 이동

454-572

`list_move()`와 `list_move_tail()`은 entry를 다른 list의 시작 또는 끝으로 각각 옮깁니다. 초기 State 0에는 `clowns`와 `sidewalk` 두 list가 있습니다.

State 0: 이동 전 두 list
clownsGrockDimitriPicAlfredo
sidewalkPio

Clowns에는 네 명, sidewalk에는 Pio가 있습니다.

.. code-block:: c

  static void circus_clowns_exit_car(struct circus_priv *circus)
  {
          struct list_head sidewalk = LIST_HEAD_INIT(sidewalk);
          struct clown *grock, *dimitri, *pic, *alfredo, *pio;
          struct clown_car *car = &circus->car;

          /* ... clown initialization, list adding ... */

          /* State 0 */

          list_move(&pic->node, &sidewalk);

          /* State 1 */

          list_move_tail(&dimitri->node, &sidewalk);

          /* State 2 */
  }

State 1에서 `list_move()`는 Pic을 sidewalk head 바로 뒤로 옮깁니다.

State 1: Pic 이동
clownsGrockDimitriAlfredo
sidewalkPicPio

Pic이 sidewalk의 첫 entry가 됩니다.

State 2에서 `list_move_tail()`은 Dimitri를 sidewalk의 tail로 옮깁니다.

State 2: Dimitri를 tail로 이동
clownsGrockAlfredo
sidewalkPicPioDimitri

Clowns에는 Grock과 Alfredo, sidewalk에는 Pic, Pio, Dimitri가 남습니다.

Source와 destination list head가 같은 list에 속한다면 `list_bulk_move_tail()`로 연속 구간을 list tail에 효율적으로 옮길 수 있습니다. 다음 code는 Pic부터 Pio까지를 sidewalk tail로 이동합니다.

.. code-block:: c

  static void circus_clowns_exit_car(struct circus_priv *circus)
  {
          struct list_head sidewalk = LIST_HEAD_INIT(sidewalk);
          struct clown *grock, *dimitri, *pic, *alfredo, *pio;
          struct clown_car *car = &circus->car;

          /* ... clown initialization, list adding ... */

          /* State 0 */

          list_move(&pic->node, &sidewalk);

          /* State 1 */

          list_move_tail(&dimitri->node, &sidewalk);

          /* State 2 */

          list_bulk_move_tail(&sidewalk, &pic->node, &pio->node);

          /* State 3 */
  }
State 3: 부분 list를 tail로 이동
sidewalkDimitriPicPio

Dimitri가 앞에 오고 Pic과 Pio 구간이 tail로 이동합니다.

`list_bulk_move_tail()`은 전달한 세 `struct list_head *`가 실제로 같은 list에 속하는지 검사하지 않습니다. 문서가 정한 제약을 벗어나 호출하면 결과를 보장할 수 없습니다.

entry 회전

573-639

Queue처럼 list를 사용할 때 흔한 write operation은 앞의 entry를 뒤로 보내는 rotation입니다. Linux는 `list_rotate_left()`와 `list_rotate_to_front()`를 제공합니다.

`list_rotate_left()`는 circular bicycle chain처럼 head 다음 entry를 tail로 옮겨 전체 list를 한 칸 회전합니다. `list_rotate_to_front()`는 지정 entry가 새 front가 될 때까지 회전합니다.

State 0: 회전 전
clownsGrockDimitriPicAlfredoPio

초기 clown 순서입니다.

.. code-block:: c

  static void circus_clowns_rotate(struct circus_priv *circus)
  {
          struct clown *grock, *dimitri, *pic, *alfredo, *pio;
          struct clown_car *car = &circus->car;

          /* ... clown initialization, list adding ... */

          /* State 0 */

          list_rotate_left(&car->clowns);

          /* State 1 */

          list_rotate_to_front(&alfredo->node, &car->clowns);

          /* State 2 */

  }
State 1: 왼쪽으로 한 칸 회전
clownsDimitriPicAlfredoPioGrock

Grock이 tail로 이동합니다.

State 2: Alfredo를 front로 회전
clownsAlfredoPioGrockDimitriPic

Alfredo 앞의 entry가 tail 쪽으로 순환 이동합니다.

entry 교환

640-682

두 entry의 위치를 바꾸는 흔한 작업에는 `list_swap()`을 사용합니다. State 0은 세 entry로 시작합니다.

State 0: 교환 전
clownsGrockDimitriPic

Grock, Dimitri, Pic 순서입니다.

.. code-block:: c

  static void circus_clowns_swap(struct circus_priv *circus)
  {
          struct clown *grock, *dimitri, *pic;
          struct clown_car *car = &circus->car;

          /* ... clown initialization, list adding ... */

          /* State 0 */

          list_swap(&dimitri->node, &pic->node);

          /* State 1 */
  }

State 1에서는 Pic과 Dimitri의 위치가 서로 바뀝니다.

State 1: 교환 뒤
clownsGrockPicDimitri

Grock, Pic, Dimitri 순서입니다.

두 list 잇기

683-757

두 circus list `knie`와 `stey`를 합치는 예제입니다. 초기 State 0은 다음과 같습니다.

State 0: splice 전
knieGrockDimitriPic
steyAlfredoPio

두 개의 독립된 circular list입니다.

두 list를 잇는 함수는 `list_splice()`입니다.

.. code-block:: c

  static void circus_clowns_splice(void)
  {
          struct clown *grock, *dimitri, *pic, *alfredo, *pio;
          struct list_head knie = LIST_HEAD_INIT(knie);
          struct list_head stey = LIST_HEAD_INIT(stey);

          /* ... Clown allocation and initialization here ... */

          list_add_tail(&grock->node, &knie);
          list_add_tail(&dimitri->node, &knie);
          list_add_tail(&pic->node, &knie);
          list_add_tail(&alfredo->node, &stey);
          list_add_tail(&pio->node, &stey);

          /* State 0 */

          list_splice(&stey, &dimitri->node);

          /* State 1 */
  }

이 호출은 `stey`의 모든 entry를 Dimitri의 `node` 다음에 삽입합니다.

State 1: list_splice() 뒤
knieGrockDimitriAlfredoPioPicknie
stey (stale head)AlfredoPioPicknie ... never returns to stey

Knie에는 모든 entry가 연결되지만 stey head는 새 list 내부를 계속 가리켜 자신에게 돌아오지 못합니다.

이 상태에서 `stey`를 `list_for_each()`로 순회하면 head로 돌아오지 않아 infinite loop가 됩니다. `list_splice()`가 donor `list_head`를 재초기화하지 않아 pointer가 이제 다른 list 내부를 가리키기 때문입니다.

이를 피하려면 `list_splice_init()`을 사용합니다. `list_splice()`와 같은 transplant를 수행한 뒤 donor `list_head`를 다시 초기화합니다.

concurrency 고려 사항

758-766

대부분의 경우 list에 대한 concurrent access와 modification은 lock으로 보호해야 합니다. Read가 많고 modification이 적은 use case에서는 list용 RCU primitive를 사용하는 편이 좋습니다. 자세한 내용은 `Documentation/RCU/listRCU.rst`를 참조하십시오.

더 읽을 자료

767-771

더 읽을 자료 (Further reading)

전체 List API

772-776

전체 List API (Full List API)

List API의 internal kernel-doc은 `include/linux/list.h`에서 가져옵니다.

.. kernel-doc:: include/linux/list.h
   :internal: