요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0+
=============
ID Allocation
=============
:Author: Matthew Wilcox
Overview
========
A common problem to solve is allocating identifiers (IDs); generally
small numbers which identify a thing. Examples include file descriptors,
process IDs, packet identifiers in networking protocols, SCSI tags
and device instance numbers. The IDR and the IDA provide a reasonable
solution to the problem to avoid everybody inventing their own. The IDR
provides the ability to map an ID to a pointer, while the IDA provides
only ID allocation, and as a result is much more memory-efficient.
The IDR interface is deprecated; please use the :doc:`XArray <xarray>`
instead.
IDR usage
=========
Start by initialising an IDR, either with DEFINE_IDR()
for statically allocated IDRs or idr_init() for dynamically
allocated IDRs.
You can call idr_alloc() to allocate an unused ID. Look up
the pointer you associated with the ID by calling idr_find()
and free the ID by calling idr_remove().
If you need to change the pointer associated with an ID, you can call
idr_replace(). One common reason to do this is to reserve an
ID by passing a ``NULL`` pointer to the allocation function; initialise the
object with the reserved ID and finally insert the initialised object
into the IDR.
Some users need to allocate IDs larger than ``INT_MAX``. So far all of
these users have been content with a ``UINT_MAX`` limit, and they use
idr_alloc_u32(). If you need IDs that will not fit in a u32,
we will work with you to address your needs.
If you need to allocate IDs sequentially, you can use
idr_alloc_cyclic(). The IDR becomes less efficient when dealing
with larger IDs, so using this function comes at a slight cost.
To perform an action on all pointers used by the IDR, you can
either use the callback-based idr_for_each() or the
iterator-style idr_for_each_entry(). You may need to use
idr_for_each_entry_continue() to continue an iteration. You can
also use idr_get_next() if the iterator doesn't fit your needs.
When you have finished using an IDR, you can call idr_destroy()
to release the memory used by the IDR. This will not free the objects
pointed to from the IDR; if you want to do that, use one of the iterators
to do it.
You can use idr_is_empty() to find out whether there are any
IDs currently allocated.
If you need to take a lock while allocating a new ID from the IDR,
you may need to pass a restrictive set of GFP flags, which can lead
to the IDR being unable to allocate memory. To work around this,
you can call idr_preload() before taking the lock, and then
idr_preload_end() after the allocation.
.. kernel-doc:: include/linux/idr.h
:doc: idr sync
IDA usage
=========
.. kernel-doc:: lib/idr.c
:doc: IDA description
Functions and structures
========================
.. kernel-doc:: include/linux/idr.h
:functions:
.. kernel-doc:: lib/idr.c
:functions:
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
문서 정보
1-8`.. SPDX-License-Identifier: GPL-2.0+`
ID 할당 (ID Allocation)
저자: Matthew Wilcox
개요
9-22흔히 해결해야 하는 문제 중 하나는 식별자(ID)를 할당하는 것입니다. 식별자는 일반적으로 어떤 대상을 구별하는 작은 숫자입니다. 파일 디스크립터, 프로세스 ID, 네트워크 프로토콜의 패킷 식별자, SCSI 태그, 장치 인스턴스 번호가 그 예입니다. IDR과 IDA는 각 사용자가 자체 구현을 새로 만들지 않도록 이 문제에 적절한 해법을 제공합니다. IDR은 ID를 포인터에 매핑할 수 있지만 IDA는 ID 할당만 제공하므로 메모리를 훨씬 효율적으로 사용합니다.
IDR 인터페이스는 더 이상 사용하지 않는 것이 권장됩니다. 대신 `:doc:`XArray <xarray>``를 사용하십시오.
IDR 사용법
23-71먼저 IDR을 초기화합니다. 정적으로 할당한 IDR에는 `DEFINE_IDR()`을 사용하고, 동적으로 할당한 IDR에는 `idr_init()`을 사용합니다.
`idr_alloc()`을 호출하면 아직 사용하지 않은 ID를 할당할 수 있습니다. `idr_find()`를 호출하면 해당 ID에 연결한 포인터를 조회할 수 있고, `idr_remove()`를 호출하면 ID를 해제할 수 있습니다.
ID에 연결된 포인터를 바꿔야 한다면 `idr_replace()`를 호출할 수 있습니다. 이 기능을 사용하는 일반적인 이유 중 하나는 할당 함수에 `NULL` 포인터를 전달하여 ID를 먼저 예약하는 것입니다. 그런 다음 예약한 ID로 객체를 초기화하고, 마지막으로 초기화된 객체를 IDR에 삽입합니다.
일부 사용자는 `INT_MAX`보다 큰 ID를 할당해야 합니다. 지금까지 이런 사용자는 모두 `UINT_MAX` 제한으로 충분했으며 `idr_alloc_u32()`를 사용합니다. u32에 들어가지 않는 ID가 필요하다면 커널 개발자와 함께 요구 사항을 해결해야 합니다.
ID를 순차적으로 할당해야 한다면 `idr_alloc_cyclic()`을 사용할 수 있습니다. IDR은 큰 ID를 다룰수록 효율이 낮아지므로 이 함수에는 약간의 비용이 따릅니다.
IDR에서 사용하는 모든 포인터에 작업을 수행하려면 콜백 기반 `idr_for_each()` 또는 반복자 방식 `idr_for_each_entry()`를 사용할 수 있습니다. 반복을 이어 가야 한다면 `idr_for_each_entry_continue()`가 필요할 수 있습니다. 반복자 방식이 요구 사항에 맞지 않으면 `idr_get_next()`도 사용할 수 있습니다.
IDR 사용을 마치면 `idr_destroy()`를 호출하여 IDR이 사용한 메모리를 해제할 수 있습니다. 이 함수는 IDR이 가리키는 객체 자체를 해제하지 않습니다. 객체까지 해제하려면 반복자 중 하나를 사용하여 직접 처리해야 합니다.
현재 할당된 ID가 있는지는 `idr_is_empty()`로 확인할 수 있습니다.
IDR에서 새 ID를 할당하는 동안 잠금을 잡아야 한다면 제한적인 GFP 플래그 집합을 전달해야 할 수 있으며, 이 때문에 IDR이 메모리를 할당하지 못할 수 있습니다. 이를 피하려면 잠금을 잡기 전에 `idr_preload()`를 호출하고 할당이 끝난 뒤 `idr_preload_end()`를 호출합니다.
.. kernel-doc:: include/linux/idr.h
:doc: idr sync
IDA 사용법
72-77.. kernel-doc:: lib/idr.c
:doc: IDA description
함수와 구조체
78-84.. kernel-doc:: include/linux/idr.h
:functions:
.. kernel-doc:: lib/idr.c
:functions:
요약과 해설
idr.rst:1-84IDR은 정수 ID를 포인터에 연결하는 자료구조이고 IDA는 포인터 매핑 없이 ID만 할당합니다. 단순한 번호 관리에는 메모리 효율이 높은 IDA가 적합하며, 새 코드는 폐기 예정인 IDR보다 XArray 사용을 우선 검토해야 합니다.
IDR의 기본 흐름은 초기화, `idr_alloc()`을 통한 할당, `idr_find()` 조회, `idr_remove()` 해제, `idr_destroy()` 정리 순서입니다. 포인터 교체, 순환 ID 할당, 전체 항목 반복, u32 범위 할당을 위한 전용 API도 제공합니다.
잠금을 잡은 상태에서 제한적인 GFP 플래그로 IDR 메모리를 확보하면 실패할 수 있습니다. 이 경우 잠금 전에 `idr_preload()`로 필요한 메모리를 준비하고, 할당 뒤 `idr_preload_end()`로 사전 할당 구간을 닫는 패턴을 사용합니다.