Documentation/driver-api/driver-model/device.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API

The Basic Device Structure

struct device 등록·reference lifetime과 sysfs attribute group의 올바른 publication 시점을 설명합니다.

Source pathDocumentation/driver-api/driver-model/device.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약과 해설

device.rst:1-120

device는 bus가 필수 field를 초기화한 뒤 core에 등록하며 reference count로 lifetime을 관리합니다. sysfs attribute는 attribute group으로 구성해 device_register() 전에 dev->groups에 연결해야 KOBJ_ADD uevent를 받은 userspace가 처음부터 완전한 interface를 볼 수 있습니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 ==========================
2 The Basic Device Structure
3 ==========================
4
5 See the kerneldoc for the struct device.
6
7
8 Programming Interface
9 ~~~~~~~~~~~~~~~~~~~~~
10 The bus driver that discovers the device uses this to register the
11 device with the core::
12
13 int device_register(struct device * dev);
14
15 The bus should initialize the following fields:
16
17 - parent
18 - name
19 - bus_id
20 - bus
21
22 A device is removed from the core when its reference count goes to
23 0. The reference count can be adjusted using::
24
25 struct device * get_device(struct device * dev);
26 void put_device(struct device * dev);
27
28 get_device() will return a pointer to the struct device passed to it
29 if the reference is not already 0 (if it's in the process of being
30 removed already).
31
32 A driver can access the lock in the device structure using::
33
34 void lock_device(struct device * dev);
35 void unlock_device(struct device * dev);
36
37
38 Attributes
39 ~~~~~~~~~~
40
41 ::
42
43 struct device_attribute {
44 struct attribute attr;
45 ssize_t (*show)(struct device *dev, struct device_attribute *attr,
46 char *buf);
47 ssize_t (*store)(struct device *dev, struct device_attribute *attr,
48 const char *buf, size_t count);
49 };
50
51 Attributes of devices can be exported by a device driver through sysfs.
52
53 Please see Documentation/filesystems/sysfs.rst for more information
54 on how sysfs works.
55
56 As explained in Documentation/core-api/kobject.rst, device attributes must be
57 created before the KOBJ_ADD uevent is generated. The only way to realize
58 that is by defining an attribute group.
59
60 Attributes are declared using a macro called DEVICE_ATTR::
61
62 #define DEVICE_ATTR(name,mode,show,store)
63
64 Example:::
65
66 static DEVICE_ATTR(type, 0444, type_show, NULL);
67 static DEVICE_ATTR(power, 0644, power_show, power_store);
68
69 Helper macros are available for common values of mode, so the above examples
70 can be simplified to:::
71
72 static DEVICE_ATTR_RO(type);
73 static DEVICE_ATTR_RW(power);
74
75 This declares two structures of type struct device_attribute with respective
76 names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be
77 organized as follows into a group::
78
79 static struct attribute *dev_attrs[] = {
80 &dev_attr_type.attr,
81 &dev_attr_power.attr,
82 NULL,
83 };
84
85 static struct attribute_group dev_group = {
86 .attrs = dev_attrs,
87 };
88
89 static const struct attribute_group *dev_groups[] = {
90 &dev_group,
91 NULL,
92 };
93
94 A helper macro is available for the common case of a single group, so the
95 above two structures can be declared using:::
96
97 ATTRIBUTE_GROUPS(dev);
98
99 This array of groups can then be associated with a device by setting the
100 group pointer in struct device before device_register() is invoked::
101
102 dev->groups = dev_groups;
103 device_register(dev);
104
105 The device_register() function will use the 'groups' pointer to create the
106 device attributes and the device_unregister() function will use this pointer
107 to remove the device attributes.
108
109 Word of warning: While the kernel allows device_create_file() and
110 device_remove_file() to be called on a device at any time, userspace has
111 strict expectations on when attributes get created. When a new device is
112 registered in the kernel, a uevent is generated to notify userspace (like
113 udev) that a new device is available. If attributes are added after the
114 device is registered, then userspace won't get notified and userspace will
115 not know about the new attributes.
116
117 This is important for device driver that need to publish additional
118 attributes for a device at driver probe time. If the device driver simply
119 calls device_create_file() on the device structure passed to it, then
120 userspace will never be notified of the new attributes.
121

3. 한국어 전문 번역

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

기본 device 구조체

1-7

`struct device`의 상세 정의는 해당 kerneldoc을 참고합니다.

Programming interface와 lifetime

8-37

device를 발견한 bus driver는 다음 함수로 device를 core에 등록합니다.

int device_register(struct device * dev);

bus는 다음 field를 초기화해야 합니다.

  • `parent`
  • `name`
  • `bus_id`
  • `bus`

device의 reference count가 0이 되면 core에서 제거됩니다. 다음 함수로 reference count를 조정합니다.

struct device * get_device(struct device * dev);
void put_device(struct device * dev);

reference가 아직 0이 아니라면 `get_device()`는 전달받은 `struct device` pointer를 반환합니다. 이미 제거 과정에 들어가 reference가 0이면 반환하지 않습니다.

driver는 다음 함수로 device 구조체 안의 lock에 접근할 수 있습니다.

void lock_device(struct device * dev);
void unlock_device(struct device * dev);
Device core lifetime
bus discovers deviceinitialize parent, name, bus_id, busdevice_registerget_device / put_devicereference count reaches zeroremove from core

등록, reference 획득·반납과 제거 조건을 나타냅니다.

Device attribute 구조체와 sysfs

38-54
::

  struct device_attribute {
        struct attribute        attr;
        ssize_t (*show)(struct device *dev, struct device_attribute *attr,
                        char *buf);
        ssize_t (*store)(struct device *dev, struct device_attribute *attr,
                         const char *buf, size_t count);
  };

device driver는 device attribute를 sysfs로 export할 수 있습니다. sysfs 동작에 대한 자세한 내용은 `Documentation/filesystems/sysfs.rst`를 참고합니다.

KOBJ_ADD 이전 attribute 선언

55-68

`Documentation/core-api/kobject.rst`의 설명처럼 device attribute는 `KOBJ_ADD` uevent를 생성하기 전에 만들어야 합니다. 이를 실현하는 유일한 방법은 attribute group을 정의하는 것입니다.

attribute는 `DEVICE_ATTR` macro로 선언합니다.

#define DEVICE_ATTR(name,mode,show,store)

예시는 다음과 같습니다.

static DEVICE_ATTR(type, 0444, type_show, NULL);
static DEVICE_ATTR(power, 0644, power_show, power_store);

Helper macro와 attribute group

69-93

흔히 사용하는 mode에는 helper macro가 있으므로 앞의 예제를 다음처럼 단순화할 수 있습니다.

static DEVICE_ATTR_RO(type);
static DEVICE_ATTR_RW(power);

이는 각각 `dev_attr_type`과 `dev_attr_power`라는 이름의 `struct device_attribute` 두 개를 선언합니다. 두 attribute는 다음처럼 하나의 group으로 구성할 수 있습니다.

static struct attribute *dev_attrs[] = {
      &dev_attr_type.attr,
      &dev_attr_power.attr,
      NULL,
};

static struct attribute_group dev_group = {
      .attrs = dev_attrs,
};

static const struct attribute_group *dev_groups[] = {
      &dev_group,
      NULL,
};
Device attribute group hierarchy
LevelObjectContents / Terminator
Attributedev_attr_type, dev_attr_powershow/store metadata
Attribute pointer arraydev_attrs[]&dev_attr_*.attr, NULL
Groupdev_group.attrs = dev_attrs
Group pointer arraydev_groups[]&dev_group, NULL
Devicedev->groupsdev_groups before registration

attribute에서 group array까지의 포함 관계를 정리했습니다.

ATTRIBUTE_GROUPS와 device 등록

94-107

group 하나만 사용하는 흔한 경우에는 다음 helper macro로 앞의 두 group 구조체를 선언할 수 있습니다.

ATTRIBUTE_GROUPS(dev);

`device_register()`를 호출하기 전에 `struct device`의 group pointer를 설정해 group array를 device와 연결합니다.

dev->groups = dev_groups;
device_register(dev);

`device_register()`는 `groups` pointer를 사용해 device attribute를 생성하고, `device_unregister()`는 같은 pointer를 사용해 device attribute를 제거합니다.

동적 attribute 생성에 대한 userspace 경고

108-120

kernel은 `device_create_file()`과 `device_remove_file()`을 언제든 device에 호출하도록 허용하지만, userspace는 attribute가 생성되는 시점에 엄격한 기대를 가집니다. 새 device가 kernel에 등록되면 udev 같은 userspace에 새 device를 알리는 uevent가 발생합니다.

device 등록 뒤 attribute를 추가하면 userspace에는 별도 notification이 가지 않으므로 새 attribute의 존재를 알지 못합니다. driver probe 시점에 device용 추가 attribute를 공개해야 하는 driver에는 특히 중요합니다. 전달받은 device 구조체에 단순히 `device_create_file()`을 호출하면 userspace는 그 새 attribute를 결코 통지받지 못합니다.

Attribute publication timing
define DEVICE_ATTR entriesbuild attribute_groupassign dev->groupsdevice_register creates attributesKOBJ_ADD uevent notifies userspace

userspace가 attribute를 발견할 수 있는 올바른 등록 순서를 나타냅니다.