← Documents Documentation/filesystems/sysfs.rst GitHub 원문 ↗

Linux 6.18.37 · Filesystems

sysfs - The filesystem for exporting kernel objects

sysfs kobject hierarchy, attribute callback, I/O 계약과 ABI 문서화의 전문 번역입니다.

Source pathDocumentation/filesystems/sysfs.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약·해설

sysfs.rst:1-435

sysfs는 kobject hierarchy와 attribute를 `/sys`의 directory·ASCII file·symlink로 투영한다. subsystem은 구체 attribute wrapper와 `sysfs_ops`를 제공하고 generic kobject 요청을 device·bus·driver callback으로 전달한다.

I/O 계약의 핵심은 PAGE_SIZE buffer와 callback 1회다. `show()`는 전체 값을 `sysfs_emit()`로 만들고 출력 byte 수를, `store()`는 소비 byte 수를 반환한다. memory에 pin된 kernel object와 실제 hardware의 존재는 별개이므로 callback이 필요한 상태 검사를 해야 한다.

Sysfs ABI 경로
kobject·kobj_typeattribute wrapper와 `sysfs_ops`PAGE_SIZE `show()`·`store()``/sys` directory·file`Documentation/ABI` 안정성 계약

kernel object에서 안정적인 user-space 파일 ABI까지다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 =====================================================
4 sysfs - _The_ filesystem for exporting kernel objects
5 =====================================================
6
7 Patrick Mochel <[email protected]>
8
9 Mike Murphy <[email protected]>
10
11 :Revised: 16 August 2011
12 :Original: 10 January 2003
13
14
15 What it is
16 ~~~~~~~~~~
17
18 sysfs is a RAM-based filesystem initially based on ramfs. It provides
19 a means to export kernel data structures, their attributes, and the
20 linkages between them to userspace.
21
22 sysfs is tied inherently to the kobject infrastructure. Please read
23 Documentation/core-api/kobject.rst for more information concerning the kobject
24 interface.
25
26
27 Using sysfs
28 ~~~~~~~~~~~
29
30 sysfs is always compiled in if CONFIG_SYSFS is defined. You can access
31 it by doing::
32
33 mount -t sysfs sysfs /sys
34
35
36 Directory Creation
37 ~~~~~~~~~~~~~~~~~~
38
39 For every kobject that is registered with the system, a directory is
40 created for it in sysfs. That directory is created as a subdirectory
41 of the kobject's parent, expressing internal object hierarchies to
42 userspace. Top-level directories in sysfs represent the common
43 ancestors of object hierarchies; i.e. the subsystems the objects
44 belong to.
45
46 sysfs internally stores a pointer to the kobject that implements a
47 directory in the kernfs_node object associated with the directory. In
48 the past this kobject pointer has been used by sysfs to do reference
49 counting directly on the kobject whenever the file is opened or closed.
50 With the current sysfs implementation the kobject reference count is
51 only modified directly by the function sysfs_schedule_callback().
52
53
54 Attributes
55 ~~~~~~~~~~
56
57 Attributes can be exported for kobjects in the form of regular files in
58 the filesystem. sysfs forwards file I/O operations to methods defined
59 for the attributes, providing a means to read and write kernel
60 attributes.
61
62 Attributes should be ASCII text files, preferably with only one value
63 per file. It is noted that it may not be efficient to contain only one
64 value per file, so it is socially acceptable to express an array of
65 values of the same type.
66
67 Mixing types, expressing multiple lines of data, and doing fancy
68 formatting of data is heavily frowned upon. Doing these things may get
69 you publicly humiliated and your code rewritten without notice.
70
71
72 An attribute definition is simply::
73
74 struct attribute {
75 char *name;
76 struct module *owner;
77 umode_t mode;
78 };
79
80
81 int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
82 void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
83
84
85 A bare attribute contains no means to read or write the value of the
86 attribute. Subsystems are encouraged to define their own attribute
87 structure and wrapper functions for adding and removing attributes for
88 a specific object type.
89
90 For example, the driver model defines struct device_attribute like::
91
92 struct device_attribute {
93 struct attribute attr;
94 ssize_t (*show)(struct device *dev, struct device_attribute *attr,
95 char *buf);
96 ssize_t (*store)(struct device *dev, struct device_attribute *attr,
97 const char *buf, size_t count);
98 };
99
100 int device_create_file(struct device *, const struct device_attribute *);
101 void device_remove_file(struct device *, const struct device_attribute *);
102
103 It also defines this helper for defining device attributes::
104
105 #define DEVICE_ATTR(_name, _mode, _show, _store) \
106 struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
107
108 For example, declaring::
109
110 static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
111
112 is equivalent to doing::
113
114 static struct device_attribute dev_attr_foo = {
115 .attr = {
116 .name = "foo",
117 .mode = S_IWUSR | S_IRUGO,
118 },
119 .show = show_foo,
120 .store = store_foo,
121 };
122
123 Note as stated in include/linux/kernel.h "OTHER_WRITABLE? Generally
124 considered a bad idea." so trying to set a sysfs file writable for
125 everyone will fail reverting to RO mode for "Others".
126
127 For the common cases sysfs.h provides convenience macros to make
128 defining attributes easier as well as making code more concise and
129 readable. The above case could be shortened to:
130
131 static struct device_attribute dev_attr_foo = __ATTR_RW(foo);
132
133 the list of helpers available to define your wrapper function is:
134
135 __ATTR_RO(name):
136 assumes default name_show and mode 0444
137 __ATTR_WO(name):
138 assumes a name_store only and is restricted to mode
139 0200 that is root write access only.
140 __ATTR_RO_MODE(name, mode):
141 for more restrictive RO access; currently
142 only use case is the EFI System Resource Table
143 (see drivers/firmware/efi/esrt.c)
144 __ATTR_RW(name):
145 assumes default name_show, name_store and setting
146 mode to 0644.
147 __ATTR_NULL:
148 which sets the name to NULL and is used as end of list
149 indicator (see: kernel/workqueue.c)
150
151 Subsystem-Specific Callbacks
152 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
153
154 When a subsystem defines a new attribute type, it must implement a
155 set of sysfs operations for forwarding read and write calls to the
156 show and store methods of the attribute owners::
157
158 struct sysfs_ops {
159 ssize_t (*show)(struct kobject *, struct attribute *, char *);
160 ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
161 };
162
163 [ Subsystems should have already defined a struct kobj_type as a
164 descriptor for this type, which is where the sysfs_ops pointer is
165 stored. See the kobject documentation for more information. ]
166
167 When a file is read or written, sysfs calls the appropriate method
168 for the type. The method then translates the generic struct kobject
169 and struct attribute pointers to the appropriate pointer types, and
170 calls the associated methods.
171
172
173 To illustrate::
174
175 #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
176
177 static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
178 char *buf)
179 {
180 struct device_attribute *dev_attr = to_dev_attr(attr);
181 struct device *dev = kobj_to_dev(kobj);
182 ssize_t ret = -EIO;
183
184 if (dev_attr->show)
185 ret = dev_attr->show(dev, dev_attr, buf);
186 if (ret >= (ssize_t)PAGE_SIZE) {
187 printk("dev_attr_show: %pS returned bad count\n",
188 dev_attr->show);
189 }
190 return ret;
191 }
192
193
194
195 Reading/Writing Attribute Data
196 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197
198 To read or write attributes, show() or store() methods must be
199 specified when declaring the attribute. The method types should be as
200 simple as those defined for device attributes::
201
202 ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
203 ssize_t (*store)(struct device *dev, struct device_attribute *attr,
204 const char *buf, size_t count);
205
206 IOW, they should take only an object, an attribute, and a buffer as parameters.
207
208
209 sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
210 method. sysfs will call the method exactly once for each read or
211 write. This forces the following behavior on the method
212 implementations:
213
214 - On read(2), the show() method should fill the entire buffer.
215 Recall that an attribute should only be exporting one value, or an
216 array of similar values, so this shouldn't be that expensive.
217
218 This allows userspace to do partial reads and forward seeks
219 arbitrarily over the entire file at will. If userspace seeks back to
220 zero or does a pread(2) with an offset of '0' the show() method will
221 be called again, rearmed, to fill the buffer.
222
223 - On write(2), sysfs expects the entire buffer to be passed during the
224 first write. sysfs then passes the entire buffer to the store() method.
225 A terminating null is added after the data on stores. This makes
226 functions like sysfs_streq() safe to use.
227
228 When writing sysfs files, userspace processes should first read the
229 entire file, modify the values it wishes to change, then write the
230 entire buffer back.
231
232 Attribute method implementations should operate on an identical
233 buffer when reading and writing values.
234
235 Other notes:
236
237 - Writing causes the show() method to be rearmed regardless of current
238 file position.
239
240 - The buffer will always be PAGE_SIZE bytes in length. On x86, this
241 is 4096.
242
243 - show() methods should return the number of bytes printed into the
244 buffer.
245
246 - New implementations of show() methods should only use sysfs_emit() or
247 sysfs_emit_at() when formatting the value to be returned to user space.
248
249 - store() should return the number of bytes used from the buffer. If the
250 entire buffer has been used, just return the count argument.
251
252 - show() or store() can always return errors. If a bad value comes
253 through, be sure to return an error.
254
255 - The object passed to the methods will be pinned in memory via sysfs
256 reference counting its embedded object. However, the physical
257 entity (e.g. device) the object represents may not be present. Be
258 sure to have a way to check this, if necessary.
259
260
261 A very simple (and naive) implementation of a device attribute is::
262
263 static ssize_t show_name(struct device *dev, struct device_attribute *attr,
264 char *buf)
265 {
266 return sysfs_emit(buf, "%s\n", dev->name);
267 }
268
269 static ssize_t store_name(struct device *dev, struct device_attribute *attr,
270 const char *buf, size_t count)
271 {
272 snprintf(dev->name, sizeof(dev->name), "%.*s",
273 (int)min(count, sizeof(dev->name) - 1), buf);
274 return count;
275 }
276
277 static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
278
279
280 (Note that the real implementation doesn't allow userspace to set the
281 name for a device.)
282
283
284 Top Level Directory Layout
285 ~~~~~~~~~~~~~~~~~~~~~~~~~~
286
287 The sysfs directory arrangement exposes the relationship of kernel
288 data structures.
289
290 The top level sysfs directory looks like::
291
292 block/
293 bus/
294 class/
295 dev/
296 devices/
297 firmware/
298 fs/
299 hypervisor/
300 kernel/
301 module/
302 power/
303
304 devices/ contains a filesystem representation of the device tree. It maps
305 directly to the internal kernel device tree, which is a hierarchy of
306 struct device.
307
308 bus/ contains flat directory layout of the various bus types in the
309 kernel. Each bus's directory contains two subdirectories::
310
311 devices/
312 drivers/
313
314 devices/ contains symlinks for each device discovered in the system
315 that point to the device's directory under /sys/devices.
316
317 drivers/ contains a directory for each device driver that is loaded
318 for devices on that particular bus (this assumes that drivers do not
319 span multiple bus types).
320
321 fs/ contains a directory for some filesystems. Currently each
322 filesystem wanting to export attributes must create its own hierarchy
323 below fs/ (see fuse/fuse.rst for an example).
324
325 module/ contains parameter values and state information for all
326 loaded system modules, for both builtin and loadable modules.
327
328 dev/ contains two directories: char/ and block/. Inside these two
329 directories there are symlinks named <major>:<minor>. These symlinks
330 point to the directories under /sys/devices for each device. /sys/dev provides a
331 quick way to lookup the sysfs interface for a device from the result of
332 a stat(2) operation.
333
334 More information on driver-model specific features can be found in
335 Documentation/driver-api/driver-model/.
336
337 block/ contains symlinks to all the block devices discovered on the system.
338 These symlinks point to directories under /sys/devices.
339
340 class/ contains a directory for each device class, grouped by functional type.
341 Each directory in class/ contains symlinks to devices in the /sys/devices directory.
342
343 firmware/ contains system firmware data and configuration such as firmware tables,
344 ACPI information, and device tree data.
345
346 hypervisor/ contains virtualization platform information and provides an interface to
347 the underlying hypervisor. It is only present when running on a virtual machine.
348
349 kernel/ contains runtime kernel parameters, configuration settings, and status.
350
351 power/ contains power management subsystem information including
352 sleep states, suspend/resume capabilities, and policies.
353
354
355 Current Interfaces
356 ~~~~~~~~~~~~~~~~~~
357
358 The following interface layers currently exist in sysfs.
359
360
361 devices (include/linux/device.h)
362 --------------------------------
363 Structure::
364
365 struct device_attribute {
366 struct attribute attr;
367 ssize_t (*show)(struct device *dev, struct device_attribute *attr,
368 char *buf);
369 ssize_t (*store)(struct device *dev, struct device_attribute *attr,
370 const char *buf, size_t count);
371 };
372
373 Declaring::
374
375 DEVICE_ATTR(_name, _mode, _show, _store);
376
377 Creation/Removal::
378
379 int device_create_file(struct device *dev, const struct device_attribute * attr);
380 void device_remove_file(struct device *dev, const struct device_attribute * attr);
381
382
383 bus drivers (include/linux/device.h)
384 ------------------------------------
385 Structure::
386
387 struct bus_attribute {
388 struct attribute attr;
389 ssize_t (*show)(const struct bus_type *, char * buf);
390 ssize_t (*store)(const struct bus_type *, const char * buf, size_t count);
391 };
392
393 Declaring::
394
395 static BUS_ATTR_RW(name);
396 static BUS_ATTR_RO(name);
397 static BUS_ATTR_WO(name);
398
399 Creation/Removal::
400
401 int bus_create_file(struct bus_type *, struct bus_attribute *);
402 void bus_remove_file(struct bus_type *, struct bus_attribute *);
403
404
405 device drivers (include/linux/device.h)
406 ---------------------------------------
407
408 Structure::
409
410 struct driver_attribute {
411 struct attribute attr;
412 ssize_t (*show)(struct device_driver *, char * buf);
413 ssize_t (*store)(struct device_driver *, const char * buf,
414 size_t count);
415 };
416
417 Declaring::
418
419 DRIVER_ATTR_RO(_name)
420 DRIVER_ATTR_RW(_name)
421
422 Creation/Removal::
423
424 int driver_create_file(struct device_driver *, const struct driver_attribute *);
425 void driver_remove_file(struct device_driver *, const struct driver_attribute *);
426
427
428 Documentation
429 ~~~~~~~~~~~~~
430
431 The sysfs directory structure and the attributes in each directory define an
432 ABI between the kernel and user space. As for any ABI, it is important that
433 this ABI is stable and properly documented. All new sysfs attributes must be
434 documented in Documentation/ABI. See also Documentation/ABI/README for more
435 information.
436

3. 한국어 전문 번역

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

목적·mount·kobject directory

1-53

sysfs는 ramfs를 바탕으로 만든 RAM 기반 파일 시스템으로 kernel 자료구조, 그 attribute, 객체 사이 연결을 user space에 내보낸다. `kobject` infrastructure와 본질적으로 결합되어 있으므로 객체 interface는 `Documentation/core-api/kobject.rst`를 함께 읽어야 한다.

`CONFIG_SYSFS`가 정의되면 항상 kernel에 compile되며 `mount -t sysfs sysfs /sys`로 접근한다.

등록된 모든 kobject에는 sysfs directory가 하나 생긴다. 부모 kobject의 하위 directory에 배치되어 내부 객체 hierarchy를 user space에 드러내고, top-level directory는 subsystem 같은 공통 ancestor를 나타낸다.

sysfs는 directory의 `kernfs_node`에 구현 kobject 포인터를 저장한다. 과거에는 file open·close 때 sysfs가 이 포인터로 kobject reference count를 직접 조절했지만 현재 구현에서 이를 직접 바꾸는 함수는 `sysfs_schedule_callback()`뿐이다.

kobject에서 sysfs directory까지
kernel에서 kobject 등록부모 kobject hierarchy 확인대응 `kernfs_node`와 directory 생성`kernfs_node`에 kobject 포인터 저장user space에 객체·연결 관계 노출

kernel 객체 hierarchy가 `/sys` 경로로 투영된다.

.. SPDX-License-Identifier: GPL-2.0

=====================================================
sysfs - _The_ filesystem for exporting kernel objects
=====================================================

Patrick Mochel        <[email protected]>

Mike Murphy <[email protected]>

:Revised:    16 August 2011
:Original:   10 January 2003


What it is
~~~~~~~~~~

sysfs is a RAM-based filesystem initially based on ramfs. It provides
a means to export kernel data structures, their attributes, and the
linkages between them to userspace.

sysfs is tied inherently to the kobject infrastructure. Please read
Documentation/core-api/kobject.rst for more information concerning the kobject
interface.


Using sysfs
~~~~~~~~~~~

sysfs is always compiled in if CONFIG_SYSFS is defined. You can access
it by doing::

    mount -t sysfs sysfs /sys


Directory Creation
~~~~~~~~~~~~~~~~~~

For every kobject that is registered with the system, a directory is
created for it in sysfs. That directory is created as a subdirectory
of the kobject's parent, expressing internal object hierarchies to
userspace. Top-level directories in sysfs represent the common
ancestors of object hierarchies; i.e. the subsystems the objects
belong to.

sysfs internally stores a pointer to the kobject that implements a
directory in the kernfs_node object associated with the directory. In
the past this kobject pointer has been used by sysfs to do reference
counting directly on the kobject whenever the file is opened or closed.
With the current sysfs implementation the kobject reference count is
only modified directly by the function sysfs_schedule_callback().

Attribute 파일의 기본 계약

54-89

kobject의 attribute는 일반 파일 형태로 export된다. sysfs가 file I/O를 attribute용 method로 전달해 kernel 값을 읽고 쓰게 한다.

attribute는 ASCII text이며 가능하면 파일 하나에 값 하나만 둔다. 효율상 같은 type의 값 배열은 허용되지만 서로 다른 type 혼합, 여러 줄 data, 복잡한 formatting은 강하게 지양한다. sysfs 파일은 안정적인 단순 ABI여야 한다.

기본 `struct attribute`는 `name`, `owner` module, permission `mode`만 가진다. `sysfs_create_file()`과 `sysfs_remove_file()`로 kobject에 추가·제거한다. 이 bare attribute 자체에는 값을 읽고 쓰는 수단이 없으므로 subsystem은 자기 객체 type용 wrapper 구조체와 helper를 정의하는 것이 권장된다.

`struct attribute`와 file helper
요소역할
`name`sysfs filename
`owner`소유 module
`mode`접근 permission
`sysfs_create_file()`kobject 아래 attribute file 생성
`sysfs_remove_file()`attribute file 제거

기본 metadata와 수명 API다.

Attributes
~~~~~~~~~~

Attributes can be exported for kobjects in the form of regular files in
the filesystem. sysfs forwards file I/O operations to methods defined
for the attributes, providing a means to read and write kernel
attributes.

Attributes should be ASCII text files, preferably with only one value
per file. It is noted that it may not be efficient to contain only one
value per file, so it is socially acceptable to express an array of
values of the same type.

Mixing types, expressing multiple lines of data, and doing fancy
formatting of data is heavily frowned upon. Doing these things may get
you publicly humiliated and your code rewritten without notice.


An attribute definition is simply::

    struct attribute {
            char                    *name;
            struct module           *owner;
            umode_t                 mode;
    };


    int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
    void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);


A bare attribute contains no means to read or write the value of the
attribute. Subsystems are encouraged to define their own attribute
structure and wrapper functions for adding and removing attributes for
a specific object type.

`device_attribute`와 정의 macro

90-150

driver model의 `struct device_attribute`는 기본 `struct attribute`와 `show()`·`store()` callback을 묶는다. `device_create_file()`과 `device_remove_file()`이 `struct device`에 이 attribute를 연결한다.

`DEVICE_ATTR(_name, _mode, _show, _store)`는 `dev_attr_<name>` 구조체를 `__ATTR`로 선언한다. 예제의 `DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo)`는 이름 `foo`, 해당 mode와 callback을 직접 채운 `struct device_attribute`와 같다.

`include/linux/kernel.h`가 경고하듯 OTHER_WRITABLE은 일반적으로 나쁜 생각이다. 모든 사용자가 sysfs file을 쓰도록 설정하려 하면 Others 부분은 read-only mode로 되돌아가 실패한다.

일반 사례는 `sysfs.h` helper로 더 간결하게 쓴다. `__ATTR_RO(name)`은 `name_show`와 0444, `__ATTR_WO(name)`은 `name_store`와 root-only 0200, `__ATTR_RO_MODE(name, mode)`는 더 제한적인 read-only, `__ATTR_RW(name)`은 `name_show`·`name_store`와 0644, `__ATTR_NULL`은 name NULL인 list terminator를 가정한다.

Sysfs attribute macro
MacroCallbackMode·용도
`__ATTR_RO(name)``name_show`0444
`__ATTR_WO(name)``name_store`0200, root write only
`__ATTR_RO_MODE(name, mode)``name_show`더 제한적인 RO mode
`__ATTR_RW(name)``name_show`, `name_store`0644
`__ATTR_NULL`없음name NULL, list 종료

callback 이름과 기본 mode 규칙이다.

For example, the driver model defines struct device_attribute like::

    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);
    };

    int device_create_file(struct device *, const struct device_attribute *);
    void device_remove_file(struct device *, const struct device_attribute *);

It also defines this helper for defining device attributes::

    #define DEVICE_ATTR(_name, _mode, _show, _store) \
    struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

For example, declaring::

    static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);

is equivalent to doing::

    static struct device_attribute dev_attr_foo = {
            .attr = {
                    .name = "foo",
                    .mode = S_IWUSR | S_IRUGO,
            },
            .show = show_foo,
            .store = store_foo,
    };

Note as stated in include/linux/kernel.h "OTHER_WRITABLE?  Generally
considered a bad idea." so trying to set a sysfs file writable for
everyone will fail reverting to RO mode for "Others".

For the common cases sysfs.h provides convenience macros to make
defining attributes easier as well as making code more concise and
readable. The above case could be shortened to:

static struct device_attribute dev_attr_foo = __ATTR_RW(foo);

the list of helpers available to define your wrapper function is:

__ATTR_RO(name):
                 assumes default name_show and mode 0444
__ATTR_WO(name):
                 assumes a name_store only and is restricted to mode
                 0200 that is root write access only.
__ATTR_RO_MODE(name, mode):
                 for more restrictive RO access; currently
                 only use case is the EFI System Resource Table
                 (see drivers/firmware/efi/esrt.c)
__ATTR_RW(name):
                 assumes default name_show, name_store and setting
                 mode to 0644.
__ATTR_NULL:
                 which sets the name to NULL and is used as end of list
                 indicator (see: kernel/workqueue.c)

Subsystem별 `sysfs_ops` forwarding

151-194

새 attribute type을 정의한 subsystem은 generic read·write를 실제 owner의 `show()`·`store()`로 전달할 `struct sysfs_ops`를 구현해야 한다. 이 포인터는 해당 type descriptor인 `struct kobj_type`에 저장된다.

file I/O가 발생하면 sysfs가 type의 적절한 method를 호출한다. method는 generic `struct kobject`와 `struct attribute` 포인터를 subsystem별 type으로 변환하고 실제 callback을 호출한다.

예제 `dev_attr_show()`는 `container_of` 기반 `to_dev_attr()`로 attribute를 `device_attribute`로 바꾸고 `kobj_to_dev()`로 device를 얻는다. `show`가 있으면 호출하며 반환 크기가 `PAGE_SIZE` 이상이면 잘못된 count를 printk로 경고한다. callback이 없을 때 초기 반환값은 `-EIO`다.

Sysfs callback forwarding
sysfs file read/write`kobj_type.sysfs_ops` 선택generic kobject·attribute 수신`container_of`·`kobj_to_dev`로 구체 type 변환owner의 `show()` 또는 `store()` 호출

generic VFS 요청을 subsystem별 callback으로 변환한다.

Subsystem-Specific Callbacks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When a subsystem defines a new attribute type, it must implement a
set of sysfs operations for forwarding read and write calls to the
show and store methods of the attribute owners::

    struct sysfs_ops {
            ssize_t (*show)(struct kobject *, struct attribute *, char *);
            ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
    };

[ Subsystems should have already defined a struct kobj_type as a
descriptor for this type, which is where the sysfs_ops pointer is
stored. See the kobject documentation for more information. ]

When a file is read or written, sysfs calls the appropriate method
for the type. The method then translates the generic struct kobject
and struct attribute pointers to the appropriate pointer types, and
calls the associated methods.


To illustrate::

    #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)

    static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
                                char *buf)
    {
            struct device_attribute *dev_attr = to_dev_attr(attr);
            struct device *dev = kobj_to_dev(kobj);
            ssize_t ret = -EIO;

            if (dev_attr->show)
                    ret = dev_attr->show(dev, dev_attr, buf);
            if (ret >= (ssize_t)PAGE_SIZE) {
                    printk("dev_attr_show: %pS returned bad count\n",
                                    dev_attr->show);
            }
            return ret;
    }


`show()`·`store()`의 PAGE_SIZE 계약

195-260

attribute를 읽거나 쓰려면 선언 때 `show()` 또는 `store()`를 지정한다. callback 인자는 object, attribute, buffer만 받도록 단순해야 한다.

sysfs는 PAGE_SIZE buffer를 할당하고 read 또는 write 한 번마다 method를 정확히 한 번 호출한다. read의 `show()`는 값 하나 또는 같은 type 배열 전체를 buffer에 채워야 한다. user space는 반환된 file image에서 부분 read와 forward seek를 자유롭게 할 수 있다. offset 0으로 seek하거나 `pread(2)` offset 0을 요청하면 `show()`가 다시 호출되어 buffer를 새로 채운다.

write에서는 첫 write에 전체 buffer가 전달된다고 기대하고 그 전부를 `store()`에 넘긴다. data 뒤에 terminating NUL을 추가하므로 `sysfs_streq()`를 안전하게 쓸 수 있다. user process는 파일 전체를 읽고 바꿀 값을 수정한 뒤 전체 buffer를 다시 쓰는 방식이 권장되며, callback은 read와 write에서 동일한 형식의 buffer를 다뤄야 한다.

write는 현재 file position과 무관하게 `show()` snapshot을 rearm한다. buffer는 항상 PAGE_SIZE이며 x86에서는 4096 byte다. `show()`는 출력 byte 수를 반환하고 새 구현은 formatting에 `sysfs_emit()` 또는 `sysfs_emit_at()`만 사용해야 한다. `store()`는 소비한 byte 수를 반환하며 전부 사용했으면 `count`를 반환한다. 두 callback은 잘못된 값 등에서 error를 반환할 수 있다.

sysfs reference counting은 callback에 전달한 embedded object를 memory에 pin하지만 그 객체가 나타내는 실제 device 같은 물리 entity가 여전히 존재한다고 보장하지 않는다. 필요하면 callback이 별도 존재 여부를 확인해야 한다.

Sysfs I/O callback 계약
항목`show()` read`store()` write
BufferPAGE_SIZE 전체 출력첫 write의 전체 buffer, 뒤에 NUL 추가
호출 횟수read cycle당 정확히 1회write당 정확히 1회
재호출seek/pread offset 0에서 rearmwrite가 show snapshot rearm
Formatting`sysfs_emit()`·`sysfs_emit_at()`동일한 ABI 형식 parse
반환출력 byte 수소비 byte 수, 전부면 `count`
오류error 반환 가능bad value에서 error 반환

read와 write의 buffer·호출·반환 규칙을 비교한다.

부분 read의 실제 동작
user가 sysfs file readsysfs가 PAGE_SIZE buffer 할당`show()` 한 번으로 전체 value 생성user가 부분 read·forward seek 수행offset 0으로 돌아오면 `show()`를 다시 호출

callback은 한 번 호출되고 sysfs가 user offset을 처리한다.

Reading/Writing Attribute Data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To read or write attributes, show() or store() methods must be
specified when declaring the attribute. The method types should be as
simple as those defined for device attributes::

    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);

IOW, they should take only an object, an attribute, and a buffer as parameters.


sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
method. sysfs will call the method exactly once for each read or
write. This forces the following behavior on the method
implementations:

- On read(2), the show() method should fill the entire buffer.
  Recall that an attribute should only be exporting one value, or an
  array of similar values, so this shouldn't be that expensive.

  This allows userspace to do partial reads and forward seeks
  arbitrarily over the entire file at will. If userspace seeks back to
  zero or does a pread(2) with an offset of '0' the show() method will
  be called again, rearmed, to fill the buffer.

- On write(2), sysfs expects the entire buffer to be passed during the
  first write. sysfs then passes the entire buffer to the store() method.
  A terminating null is added after the data on stores. This makes
  functions like sysfs_streq() safe to use.

  When writing sysfs files, userspace processes should first read the
  entire file, modify the values it wishes to change, then write the
  entire buffer back.

  Attribute method implementations should operate on an identical
  buffer when reading and writing values.

Other notes:

- Writing causes the show() method to be rearmed regardless of current
  file position.

- The buffer will always be PAGE_SIZE bytes in length. On x86, this
  is 4096.

- show() methods should return the number of bytes printed into the
  buffer.

- New implementations of show() methods should only use sysfs_emit() or
  sysfs_emit_at() when formatting the value to be returned to user space.

- store() should return the number of bytes used from the buffer. If the
  entire buffer has been used, just return the count argument.

- show() or store() can always return errors. If a bad value comes
  through, be sure to return an error.

- The object passed to the methods will be pinned in memory via sysfs
  reference counting its embedded object. However, the physical
  entity (e.g. device) the object represents may not be present. Be
  sure to have a way to check this, if necessary.

단순 device attribute 예제

261-283

예제 `show_name()`은 `sysfs_emit(buf, "%s\n", dev->name)`로 device 이름과 newline을 출력하고 byte 수를 반환한다. `store_name()`은 `count`와 destination 크기 중 안전한 길이를 골라 `snprintf`로 이름을 복사한 뒤 `count`를 반환한다.

이 callback은 `DEVICE_ATTR(name, S_IRUGO, show_name, store_name)`으로 연결된다. 설명을 위한 단순 예제이며 실제 구현은 user space가 device 이름을 설정하지 못하게 한다.

Device name attribute 예제
`DEVICE_ATTR(name, ...)` 선언read → `show_name()``sysfs_emit()`로 이름과 newline 출력write → `store_name()`입력 길이를 제한해 name buffer에 복사

선언과 callback 연결을 보여 준다.

A very simple (and naive) implementation of a device attribute is::

    static ssize_t show_name(struct device *dev, struct device_attribute *attr,
                            char *buf)
    {
            return sysfs_emit(buf, "%s\n", dev->name);
    }

    static ssize_t store_name(struct device *dev, struct device_attribute *attr,
                            const char *buf, size_t count)
    {
            snprintf(dev->name, sizeof(dev->name), "%.*s",
                    (int)min(count, sizeof(dev->name) - 1), buf);
            return count;
    }

    static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);


(Note that the real implementation doesn't allow userspace to set the
name for a device.)

Top-level `/sys` directory layout

284-353

sysfs directory 배치는 kernel 자료구조 관계를 노출한다. top level에는 `block/`, `bus/`, `class/`, `dev/`, `devices/`, `firmware/`, `fs/`, `hypervisor/`, `kernel/`, `module/`, `power/`가 있다.

`devices/`는 `struct device` hierarchy인 내부 kernel device tree를 그대로 파일 시스템으로 표현한다. `bus/`는 bus type별 평면 directory이며 각 bus의 `devices/`에는 `/sys/devices`의 실제 device directory를 가리키는 symlink, `drivers/`에는 그 bus에 load된 driver별 directory가 있다.

`fs/`는 attribute를 export하는 일부 파일 시스템이 자체 hierarchy를 만드는 곳이다. `module/`은 built-in과 loadable module 모두의 parameter와 상태를 담는다. `dev/char`와 `dev/block`에는 `<major>:<minor>` symlink가 있어 `stat(2)` 결과에서 해당 `/sys/devices` interface를 빠르게 찾는다.

`block/`은 발견된 모든 block device의 `/sys/devices` symlink, `class/`는 기능 유형별 device class와 device symlink를 담는다. `firmware/`는 firmware table·ACPI·device tree data, `hypervisor/`는 VM에서만 나타나는 virtualization platform interface, `kernel/`은 runtime parameter·configuration·status, `power/`는 sleep·suspend/resume·policy를 제공한다.

Top-level sysfs directory
Directory내용
`devices/`실제 kernel `struct device` tree
`bus/`bus별 devices symlink와 drivers
`class/`기능 class별 device symlink
`dev/`char/block의 `<major>:<minor>` lookup
`block/`모든 block device symlink
`fs/`파일 시스템별 attribute hierarchy
`module/`built-in·loadable module parameter와 상태
`firmware/`firmware table, ACPI, device tree
`hypervisor/`VM의 hypervisor 정보·interface
`kernel/`runtime kernel 설정·상태
`power/`power management 상태·정책

각 최상위 directory의 핵심 역할이다.

Top Level Directory Layout
~~~~~~~~~~~~~~~~~~~~~~~~~~

The sysfs directory arrangement exposes the relationship of kernel
data structures.

The top level sysfs directory looks like::

    block/
    bus/
    class/
    dev/
    devices/
    firmware/
    fs/
    hypervisor/
    kernel/
    module/
    power/

devices/ contains a filesystem representation of the device tree. It maps
directly to the internal kernel device tree, which is a hierarchy of
struct device.

bus/ contains flat directory layout of the various bus types in the
kernel. Each bus's directory contains two subdirectories::

        devices/
        drivers/

devices/ contains symlinks for each device discovered in the system
that point to the device's directory under /sys/devices.

drivers/ contains a directory for each device driver that is loaded
for devices on that particular bus (this assumes that drivers do not
span multiple bus types).

fs/ contains a directory for some filesystems.  Currently each
filesystem wanting to export attributes must create its own hierarchy
below fs/ (see fuse/fuse.rst for an example).

module/ contains parameter values and state information for all
loaded system modules, for both builtin and loadable modules.

dev/ contains two directories: char/ and block/. Inside these two
directories there are symlinks named <major>:<minor>.  These symlinks
point to the directories under /sys/devices for each device.  /sys/dev provides a
quick way to lookup the sysfs interface for a device from the result of
a stat(2) operation.

More information on driver-model specific features can be found in
Documentation/driver-api/driver-model/.

block/ contains symlinks to all the block devices discovered on the system.
These symlinks point to directories under /sys/devices.

class/ contains a directory for each device class, grouped by functional type.
Each directory in class/ contains symlinks to devices in the /sys/devices directory.

firmware/ contains system firmware data and configuration such as firmware tables,
ACPI information, and device tree data.

hypervisor/ contains virtualization platform information and provides an interface to
the underlying hypervisor.  It is only present when running on a virtual machine.

kernel/ contains runtime kernel parameters, configuration settings, and status.

power/ contains power management subsystem information including
sleep states, suspend/resume capabilities, and policies.

Device attribute interface

354-382

현재 sysfs의 device layer는 `include/linux/device.h`의 `struct device_attribute`를 사용한다. 구조체는 기본 `attribute`와 device를 받는 `show()`·`store()` callback을 가진다.

`DEVICE_ATTR(_name, _mode, _show, _store)`로 선언하고 `device_create_file()`과 `device_remove_file()`로 특정 `struct device` 아래에 생성·제거한다.

Device sysfs interface
단계API
구조`struct device_attribute`
선언`DEVICE_ATTR(_name, _mode, _show, _store)`
생성`device_create_file()`
제거`device_remove_file()`

구조·선언·수명 API를 묶어 본다.


Current Interfaces
~~~~~~~~~~~~~~~~~~

The following interface layers currently exist in sysfs.


devices (include/linux/device.h)
--------------------------------
Structure::

    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);
    };

Declaring::

    DEVICE_ATTR(_name, _mode, _show, _store);

Creation/Removal::

    int device_create_file(struct device *dev, const struct device_attribute * attr);
    void device_remove_file(struct device *dev, const struct device_attribute * attr);

Bus·driver attribute interface

383-426

bus layer의 `struct bus_attribute`는 기본 attribute와 `const struct bus_type *`를 받는 `show()`·`store()`를 가진다. `BUS_ATTR_RW`, `BUS_ATTR_RO`, `BUS_ATTR_WO`로 선언하고 `bus_create_file()`·`bus_remove_file()`로 관리한다.

device driver layer의 `struct driver_attribute`는 `struct device_driver *`를 받는 callback을 가진다. `DRIVER_ATTR_RO`, `DRIVER_ATTR_RW`로 선언하고 `driver_create_file()`·`driver_remove_file()`로 생성·제거한다.

Sysfs interface layer 비교
LayerAttribute선언생성·제거
device`device_attribute``DEVICE_ATTR``device_create_file` / `device_remove_file`
bus`bus_attribute``BUS_ATTR_RO/RW/WO``bus_create_file` / `bus_remove_file`
driver`driver_attribute``DRIVER_ATTR_RO/RW``driver_create_file` / `driver_remove_file`

callback owner type과 helper family가 다르다.

bus drivers (include/linux/device.h)
------------------------------------
Structure::

    struct bus_attribute {
            struct attribute        attr;
            ssize_t (*show)(const struct bus_type *, char * buf);
            ssize_t (*store)(const struct bus_type *, const char * buf, size_t count);
    };

Declaring::

    static BUS_ATTR_RW(name);
    static BUS_ATTR_RO(name);
    static BUS_ATTR_WO(name);

Creation/Removal::

    int bus_create_file(struct bus_type *, struct bus_attribute *);
    void bus_remove_file(struct bus_type *, struct bus_attribute *);


device drivers (include/linux/device.h)
---------------------------------------

Structure::

    struct driver_attribute {
            struct attribute        attr;
            ssize_t (*show)(struct device_driver *, char * buf);
            ssize_t (*store)(struct device_driver *, const char * buf,
                            size_t count);
    };

Declaring::

    DRIVER_ATTR_RO(_name)
    DRIVER_ATTR_RW(_name)

Creation/Removal::

    int driver_create_file(struct device_driver *, const struct driver_attribute *);
    void driver_remove_file(struct device_driver *, const struct driver_attribute *);

Sysfs ABI 문서화 의무

427-435

sysfs directory 구조와 각 directory의 attribute는 kernel과 user space 사이 ABI를 정의한다. 다른 ABI와 마찬가지로 안정적으로 유지하고 제대로 문서화해야 한다.

새 sysfs attribute는 모두 `Documentation/ABI`에 문서화해야 하며 세부 규칙은 `Documentation/ABI/README`를 따른다.

새 sysfs attribute의 완료 조건
attribute 이름·mode·callback 설계단순하고 안정적인 text ABI 확정`Documentation/ABI` 항목 작성ABI review와 구현 반영이후 user space 호환성 유지

code 추가만으로는 충분하지 않다.


Documentation
~~~~~~~~~~~~~

The sysfs directory structure and the attributes in each directory define an
ABI between the kernel and user space. As for any ABI, it is important that
this ABI is stable and properly documented. All new sysfs attributes must be
documented in Documentation/ABI. See also Documentation/ABI/README for more
information.