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

Linux 6.18.37 · Core API

The genalloc/genpool subsystem

특수 목적 memory range를 위한 generic pool allocator의 생성, memory 등록, DMA 할당, 전략 선택과 수명 관리 API를 설명합니다.

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

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

1. 요약·해설

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

요약과 해설

genalloc.rst:1-144

genpool은 장치 memory처럼 일반 allocator가 직접 다루기 어려운 address range에 ad hoc allocator를 반복 구현하지 않도록 만든 generic subsystem입니다. pool 생성 뒤에는 별도로 memory range를 추가해야 실제 allocation이 가능합니다.

`min_alloc_order`는 byte 단위 최소 할당 granularity를 정합니다. DMA용 pool은 `gen_pool_add_virt()`로 virtual address와 physical address를 연결한 뒤 `gen_pool_dma_alloc()`을 사용해야 합니다.

기본 first-fit 외에도 alignment, order alignment, best-fit, fixed-offset algorithm을 선택할 수 있습니다. pool을 파괴할 때 outstanding allocation이 남으면 `BUG()`가 발생하므로 device-managed 수명 또는 엄격한 반환 순서를 사용해야 합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 The genalloc/genpool subsystem
2 ==============================
3
4 There are a number of memory-allocation subsystems in the kernel, each
5 aimed at a specific need. Sometimes, however, a kernel developer needs to
6 implement a new allocator for a specific range of special-purpose memory;
7 often that memory is located on a device somewhere. The author of the
8 driver for that device can certainly write a little allocator to get the
9 job done, but that is the way to fill the kernel with dozens of poorly
10 tested allocators. Back in 2005, Jes Sorensen lifted one of those
11 allocators from the sym53c8xx_2 driver and posted_ it as a generic module
12 for the creation of ad hoc memory allocators. This code was merged
13 for the 2.6.13 release; it has been modified considerably since then.
14
15 .. _posted: https://lwn.net/Articles/125842/
16
17 Code using this allocator should include <linux/genalloc.h>. The action
18 begins with the creation of a pool using one of:
19
20 .. kernel-doc:: lib/genalloc.c
21 :functions: gen_pool_create
22
23 .. kernel-doc:: lib/genalloc.c
24 :functions: devm_gen_pool_create
25
26 A call to gen_pool_create() will create a pool. The granularity of
27 allocations is set with min_alloc_order; it is a log-base-2 number like
28 those used by the page allocator, but it refers to bytes rather than pages.
29 So, if min_alloc_order is passed as 3, then all allocations will be a
30 multiple of eight bytes. Increasing min_alloc_order decreases the memory
31 required to track the memory in the pool. The nid parameter specifies
32 which NUMA node should be used for the allocation of the housekeeping
33 structures; it can be -1 if the caller doesn't care.
34
35 The "managed" interface devm_gen_pool_create() ties the pool to a
36 specific device. Among other things, it will automatically clean up the
37 pool when the given device is destroyed.
38
39 A pool is shut down with:
40
41 .. kernel-doc:: lib/genalloc.c
42 :functions: gen_pool_destroy
43
44 It's worth noting that, if there are still allocations outstanding from the
45 given pool, this function will take the rather extreme step of invoking
46 BUG(), crashing the entire system. You have been warned.
47
48 A freshly created pool has no memory to allocate. It is fairly useless in
49 that state, so one of the first orders of business is usually to add memory
50 to the pool. That can be done with one of:
51
52 .. kernel-doc:: include/linux/genalloc.h
53 :functions: gen_pool_add
54
55 .. kernel-doc:: lib/genalloc.c
56 :functions: gen_pool_add_owner
57
58 A call to gen_pool_add() will place the size bytes of memory
59 starting at addr (in the kernel's virtual address space) into the given
60 pool, once again using nid as the node ID for ancillary memory allocations.
61 The gen_pool_add_virt() variant associates an explicit physical
62 address with the memory; this is only necessary if the pool will be used
63 for DMA allocations.
64
65 The functions for allocating memory from the pool (and putting it back)
66 are:
67
68 .. kernel-doc:: include/linux/genalloc.h
69 :functions: gen_pool_alloc
70
71 .. kernel-doc:: lib/genalloc.c
72 :functions: gen_pool_dma_alloc
73
74 .. kernel-doc:: lib/genalloc.c
75 :functions: gen_pool_free_owner
76
77 As one would expect, gen_pool_alloc() will allocate size< bytes
78 from the given pool. The gen_pool_dma_alloc() variant allocates
79 memory for use with DMA operations, returning the associated physical
80 address in the space pointed to by dma. This will only work if the memory
81 was added with gen_pool_add_virt(). Note that this function
82 departs from the usual genpool pattern of using unsigned long values to
83 represent kernel addresses; it returns a void * instead.
84
85 That all seems relatively simple; indeed, some developers clearly found it
86 to be too simple. After all, the interface above provides no control over
87 how the allocation functions choose which specific piece of memory to
88 return. If that sort of control is needed, the following functions will be
89 of interest:
90
91 .. kernel-doc:: lib/genalloc.c
92 :functions: gen_pool_alloc_algo_owner
93
94 .. kernel-doc:: lib/genalloc.c
95 :functions: gen_pool_set_algo
96
97 Allocations with gen_pool_alloc_algo() specify an algorithm to be
98 used to choose the memory to be allocated; the default algorithm can be set
99 with gen_pool_set_algo(). The data value is passed to the
100 algorithm; most ignore it, but it is occasionally needed. One can,
101 naturally, write a special-purpose algorithm, but there is a fair set
102 already available:
103
104 - gen_pool_first_fit is a simple first-fit allocator; this is the default
105 algorithm if none other has been specified.
106
107 - gen_pool_first_fit_align forces the allocation to have a specific
108 alignment (passed via data in a genpool_data_align structure).
109
110 - gen_pool_first_fit_order_align aligns the allocation to the order of the
111 size. A 60-byte allocation will thus be 64-byte aligned, for example.
112
113 - gen_pool_best_fit, as one would expect, is a simple best-fit allocator.
114
115 - gen_pool_fixed_alloc allocates at a specific offset (passed in a
116 genpool_data_fixed structure via the data parameter) within the pool.
117 If the indicated memory is not available the allocation fails.
118
119 There is a handful of other functions, mostly for purposes like querying
120 the space available in the pool or iterating through chunks of memory.
121 Most users, however, should not need much beyond what has been described
122 above. With luck, wider awareness of this module will help to prevent the
123 writing of special-purpose memory allocators in the future.
124
125 .. kernel-doc:: lib/genalloc.c
126 :functions: gen_pool_virt_to_phys
127
128 .. kernel-doc:: lib/genalloc.c
129 :functions: gen_pool_for_each_chunk
130
131 .. kernel-doc:: lib/genalloc.c
132 :functions: gen_pool_has_addr
133
134 .. kernel-doc:: lib/genalloc.c
135 :functions: gen_pool_avail
136
137 .. kernel-doc:: lib/genalloc.c
138 :functions: gen_pool_size
139
140 .. kernel-doc:: lib/genalloc.c
141 :functions: gen_pool_get
142
143 .. kernel-doc:: lib/genalloc.c
144 :functions: of_gen_pool_get
145

3. 한국어 전문 번역

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

genalloc/genpool의 배경

1-16

The genalloc/genpool subsystem

커널에는 특정 목적에 맞춘 여러 memory-allocation subsystem이 있습니다. 그러나 커널 개발자가 특수 목적 memory의 특정 range를 위한 새 allocator를 구현해야 할 때가 있으며, 이 memory는 장치에 있는 경우가 많습니다.

장치 driver 작성자가 작은 allocator를 직접 만들 수도 있지만, 그렇게 하면 커널이 제대로 테스트되지 않은 수십 개의 allocator로 가득 차게 됩니다. 2005년에 Jes Sorensen은 sym53c8xx_2 driver의 allocator 하나를 떼어내 ad hoc memory allocator를 만드는 generic module로 게시했습니다.

이 코드는 2.6.13 release에 merge되었으며 그 뒤로 상당히 많이 수정되었습니다.

pool 생성과 할당 단위

17-38

이 allocator를 사용하는 코드는 `<linux/genalloc.h>`를 include해야 합니다. 다음 함수 중 하나로 pool을 생성합니다.

.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_create                
.. kernel-doc:: lib/genalloc.c
   :functions: devm_gen_pool_create

`gen_pool_create()`는 pool을 생성합니다. allocation granularity는 `min_alloc_order`로 정하며, page allocator처럼 log-base-2 값이지만 page가 아니라 byte를 기준으로 합니다. 예를 들어 `min_alloc_order`가 3이면 모든 allocation은 8 byte의 배수입니다.

`min_alloc_order`를 키우면 pool memory 추적에 필요한 memory가 줄어듭니다. `nid` parameter는 housekeeping structure를 어느 NUMA node에 할당할지 지정하며, 호출자가 상관하지 않으면 -1을 사용할 수 있습니다.

managed interface인 `devm_gen_pool_create()`는 pool을 특정 device에 연결합니다. 이 방식은 지정한 device가 파괴될 때 pool도 자동으로 정리하는 등의 수명 관리를 제공합니다.

pool 종료와 미반환 할당

39-47

pool은 다음 함수로 종료합니다.

.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_destroy

해당 pool에 아직 반환되지 않은 allocation이 남아 있으면 이 함수는 매우 강경하게 `BUG()`를 호출해 전체 system을 crash시킵니다. 반드시 모든 allocation을 먼저 반환해야 합니다.

pool에 memory 추가

48-64

새로 만든 pool에는 할당할 memory가 없습니다. 따라서 보통 가장 먼저 다음 함수 중 하나로 memory를 pool에 추가합니다.

.. kernel-doc:: include/linux/genalloc.h
   :functions: gen_pool_add
.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_add_owner

`gen_pool_add()`는 kernel virtual address space의 `addr`에서 시작하는 `size` byte memory를 지정한 pool에 넣습니다. 부가 memory allocation을 위한 node ID로 다시 `nid`를 사용합니다.

`gen_pool_add_virt()` variant는 이 memory에 명시적인 physical address를 연결합니다. pool을 DMA allocation에 사용할 때만 필요합니다.

pool memory 할당과 반환

65-84

pool에서 memory를 할당하고 반환하는 함수는 다음과 같습니다.

.. kernel-doc:: include/linux/genalloc.h
   :functions: gen_pool_alloc
.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_dma_alloc
.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_free_owner

`gen_pool_alloc()`은 지정한 pool에서 `size<` byte를 할당합니다. `gen_pool_dma_alloc()` variant는 DMA operation에 사용할 memory를 할당하고 `dma`가 가리키는 공간에 연결된 physical address를 반환합니다.

DMA variant는 memory를 `gen_pool_add_virt()`로 추가한 경우에만 동작합니다. 이 함수는 kernel address를 `unsigned long`로 표현하는 일반적인 genpool pattern과 달리 `void *`를 반환합니다.

할당 알고리즘 선택

85-118

기본 interface는 allocation function이 정확히 어느 memory 조각을 반환할지 제어하지 않습니다. 이러한 제어가 필요하면 다음 함수들이 유용합니다.

.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_alloc_algo_owner
.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_set_algo

`gen_pool_alloc_algo()`를 이용한 allocation은 할당할 memory를 선택하는 algorithm을 지정하며, `gen_pool_set_algo()`로 default algorithm을 설정할 수 있습니다. `data` 값은 algorithm에 전달됩니다. 대부분은 이를 무시하지만 일부 algorithm에는 필요합니다.

특수 목적 algorithm을 직접 작성할 수도 있지만 다음 구현이 이미 제공됩니다.

  • `gen_pool_first_fit`: 단순 first-fit allocator이며 다른 algorithm을 지정하지 않았을 때의 기본값
  • `gen_pool_first_fit_align`: `genpool_data_align` structure의 `data`로 전달한 alignment를 강제
  • `gen_pool_first_fit_order_align`: size의 order에 맞춰 정렬하며, 예를 들어 60-byte allocation은 64-byte aligned
  • `gen_pool_best_fit`: 단순 best-fit allocator
  • `gen_pool_fixed_alloc`: `data` parameter의 `genpool_data_fixed` structure로 전달한 pool 내부 특정 offset에 할당하며, 지정 memory를 사용할 수 없으면 실패

조회와 chunk 순회 함수

119-144

그 밖에도 pool에서 사용 가능한 공간을 조회하거나 memory chunk를 순회하는 등의 함수가 있습니다. 하지만 대부분의 사용자는 앞서 설명한 기능 이상을 필요로 하지 않습니다. 이 module이 널리 알려지면 앞으로 특수 목적 memory allocator를 새로 작성하는 일을 줄일 수 있습니다.

.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_virt_to_phys
.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_for_each_chunk
.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_has_addr
.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_avail
.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_size
.. kernel-doc:: lib/genalloc.c
   :functions: gen_pool_get
.. kernel-doc:: lib/genalloc.c
   :functions: of_gen_pool_get