요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=============================
The Linux Kernel Device Model
=============================
Patrick Mochel <mochel@digitalimplant.org>
Drafted 26 August 2002
Updated 31 January 2006
Overview
~~~~~~~~
The Linux Kernel Driver Model is a unification of all the disparate driver
models that were previously used in the kernel. It is intended to augment the
bus-specific drivers for bridges and devices by consolidating a set of data
and operations into globally accessible data structures.
Traditional driver models implemented some sort of tree-like structure
(sometimes just a list) for the devices they control. There wasn't any
uniformity across the different bus types.
The current driver model provides a common, uniform data model for describing
a bus and the devices that can appear under the bus. The unified bus
model includes a set of common attributes which all buses carry, and a set
of common callbacks, such as device discovery during bus probing, bus
shutdown, bus power management, etc.
The common device and bridge interface reflects the goals of the modern
computer: namely the ability to do seamless device "plug and play", power
management, and hot plug. In particular, the model dictated by Intel and
Microsoft (namely ACPI) ensures that almost every device on almost any bus
on an x86-compatible system can work within this paradigm. Of course,
not every bus is able to support all such operations, although most
buses support most of those operations.
Downstream Access
~~~~~~~~~~~~~~~~~
Common data fields have been moved out of individual bus layers into a common
data structure. These fields must still be accessed by the bus layers,
and sometimes by the device-specific drivers.
Other bus layers are encouraged to do what has been done for the PCI layer.
struct pci_dev now looks like this::
struct pci_dev {
...
struct device dev; /* Generic device interface */
...
};
Note first that the struct device dev within the struct pci_dev is
statically allocated. This means only one allocation on device discovery.
Note also that that struct device dev is not necessarily defined at the
front of the pci_dev structure. This is to make people think about what
they're doing when switching between the bus driver and the global driver,
and to discourage meaningless and incorrect casts between the two.
The PCI bus layer freely accesses the fields of struct device. It knows about
the structure of struct pci_dev, and it should know the structure of struct
device. Individual PCI device drivers that have been converted to the current
driver model generally do not and should not touch the fields of struct device,
unless there is a compelling reason to do so.
The above abstraction prevents unnecessary pain during transitional phases.
If it were not done this way, then when a field was renamed or removed, every
downstream driver would break. On the other hand, if only the bus layer
(and not the device layer) accesses the struct device, it is only the bus
layer that needs to change.
User Interface
~~~~~~~~~~~~~~
By virtue of having a complete hierarchical view of all the devices in the
system, exporting a complete hierarchical view to userspace becomes relatively
easy. This has been accomplished by implementing a special purpose virtual
file system named sysfs.
Almost all mainstream Linux distros mount this filesystem automatically; you
can see some variation of the following in the output of the "mount" command::
$ mount
...
none on /sys type sysfs (rw,noexec,nosuid,nodev)
...
$
The auto-mounting of sysfs is typically accomplished by an entry similar to
the following in the /etc/fstab file::
none /sys sysfs defaults 0 0
or something similar in the /lib/init/fstab file on Debian-based systems::
none /sys sysfs nodev,noexec,nosuid 0 0
If sysfs is not automatically mounted, you can always do it manually with::
# mount -t sysfs sysfs /sys
Whenever a device is inserted into the tree, a directory is created for it.
This directory may be populated at each layer of discovery - the global layer,
the bus layer, or the device layer.
The global layer currently creates two files - 'name' and 'power'. The
former only reports the name of the device. The latter reports the
current power state of the device. It will also be used to set the current
power state.
The bus layer may also create files for the devices it finds while probing the
bus. For example, the PCI layer currently creates 'irq' and 'resource' files
for each PCI device.
A device-specific driver may also export files in its directory to expose
device-specific data or tunable interfaces.
More information about the sysfs directory layout can be found in
the other documents in this directory and in the file
Documentation/filesystems/sysfs.rst.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
문서 정보
1-10문서 제목은 `The Linux Kernel Device Model`이며 Patrick Mochel `<mochel@digitalimplant.org>`이 작성했습니다. 2002년 8월 26일(`Drafted 26 August 2002`) 초안을 만들고 2006년 1월 31일(`Updated 31 January 2006`) 갱신했습니다.
통합 Linux Kernel Driver Model
11-37Linux Kernel Driver Model은 이전 kernel에서 따로 사용하던 여러 driver model을 통합합니다. bridge와 device용 bus-specific driver를 대체하기보다, 공통 data와 operation을 globally accessible data structure에 모아 보강합니다.
전통적인 model은 제어 device를 tree 또는 단순 list로 표현했지만 bus type 사이에 통일성이 없었습니다. 현재 model은 bus와 그 아래 나타날 수 있는 device를 설명하는 uniform data model, 모든 bus가 가지는 common attribute, bus probing 중 device discovery·shutdown·power management 같은 common callback을 제공합니다.
공통 device·bridge interface는 seamless device `plug and play`, power management, hot plug이라는 현대 system 목표를 반영합니다. ACPI가 대표하는 Intel·Microsoft model 덕분에 x86-compatible system의 거의 모든 bus와 device가 이 paradigm에서 동작할 수 있습니다. 모든 bus가 모든 operation을 지원하지는 않지만 대부분은 대부분의 operation을 지원합니다.
bus별 model에서 공통 model로 이동한 요소입니다.
Downstream access와 embedded device
38-75common data field는 개별 bus layer에서 공통 구조체로 이동했지만 bus layer와 때로 device-specific driver가 접근해야 합니다. 다른 bus도 PCI layer의 방식을 따르는 것이 권장됩니다. 현재 `struct pci_dev`는 generic device interface를 embedded member로 포함합니다.
struct pci_dev {
...
struct device dev; /* Generic device interface */
...
};
`struct pci_dev` 안의 `struct device dev`는 정적으로 할당되어 device discovery 때 allocation 한 번만 필요합니다. 이 member를 구조체 맨 앞에 둘 필요는 없습니다. bus driver와 global driver object 사이 전환을 의식하게 하고 의미 없고 잘못된 cast를 억제하기 위해서입니다.
PCI bus layer는 `struct pci_dev`와 `struct device` 구조를 모두 알므로 generic field에 자유롭게 접근합니다. 현재 model로 변환된 개별 PCI device driver는 강한 이유가 없으면 `struct device` field를 직접 만지지 않아야 합니다.
이 abstraction은 transition 동안 downstream driver의 불필요한 breakage를 막습니다. generic field가 rename·remove될 때 device driver가 직접 접근하지 않고 bus layer만 접근하면 bus layer만 수정하면 됩니다.
PCI 예제의 ownership과 변경 영향 범위를 나타냅니다.
sysfs userspace interface
76-124system의 모든 device를 완전한 hierarchy로 볼 수 있으므로 userspace에도 같은 view를 export하기 쉬워졌고, 이를 위해 sysfs라는 special-purpose virtual filesystem을 구현했습니다.
대부분의 mainstream Linux distribution은 sysfs를 자동 mount하며 `mount` output에서 다음과 비슷한 항목을 볼 수 있습니다.
$ mount
...
none on /sys type sysfs (rw,noexec,nosuid,nodev)
...
$
자동 mount는 보통 `/etc/fstab`에 다음과 같은 entry를 둡니다.
none /sys sysfs defaults 0 0
Debian 계열은 `/lib/init/fstab`에 다음과 비슷한 entry를 둘 수 있습니다.
none /sys sysfs nodev,noexec,nosuid 0 0
자동 mount되지 않으면 수동으로 mount할 수 있습니다.
# mount -t sysfs sysfs /sys
device가 tree에 삽입될 때마다 directory를 만들며 global, bus, device discovery layer 각각이 내용을 추가할 수 있습니다. global layer는 현재 `name`과 `power` file을 만들고 전자는 device 이름, 후자는 현재 power state를 보고하며 향후 설정에도 사용합니다.
bus layer도 probing 중 찾은 device에 file을 만들 수 있습니다. PCI layer는 각 PCI device에 `irq`와 `resource` file을 만듭니다. device-specific driver도 device-specific data 또는 tunable interface를 directory에 export할 수 있습니다. 자세한 layout은 이 directory의 다른 문서와 `Documentation/filesystems/sysfs.rst`를 참고합니다.
각 layer가 생성하는 대표 file을 정리했습니다.
요약과 해설
overview.rst:1-124통합 driver model은 bus-specific implementation에 공통 struct device와 callback을 embed해 변경 영향을 bus layer에 격리하고, 완전한 device hierarchy를 sysfs로 userspace에 제공합니다.