summaryrefslogtreecommitdiff
path: root/Documentation/translations/zh_CN/doc-guide/kernel-doc.rst
blob: 82ec84470c0b873f09b43966c396cfd88b2f9059 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
.. include:: ../disclaimer-zh_CN.rst

:Original: Documentation/doc-guide/kernel-doc.rst

:译者: 吴想成 Wu XiangCheng <bobwxc@email.cn>

编写kernel-doc注释
==================

Linux内核源文件可以包含kernel-doc格式的结构化文档注释,用以描述代码的函数、
类型和设计。将文档嵌入源文件更容易保持文档最新。

.. note:: 内核文档格式与javadoc、gtk-doc或Doxygen看似很相似,但由于历史原因,
          实际有着明显的不同。内核源包含成千上万个kernel-doc注释。请坚持遵循
          此处描述的风格。

.. note:: kernel-doc无法包含Rust代码:请参考 Documentation/rust/docs.rst 。

从注释中提取kernel-doc结构,并从中生成适当的 `Sphinx C 域`_ 函数和带有锚点的
类型描述。这些注释将被过滤以生成特殊kernel-doc高亮和交叉引用。详见下文。

.. _Sphinx C 域: http://www.sphinx-doc.org/en/stable/domains.html

使用 ``EXPORT_SYMBOL`` 或 ``EXPORT_SYMBOL_GPL`` 导出到可加载模块的每个函数都
应该有一个kernel-doc注释。模块使用的头文件中的函数和数据结构也应该有
kernel-doc注释。

对于其他内核文件(未标记为 ``static`` )中外部可见的函数,提供kernel-doc格式
的文档是一个很好的实践。我们也建议为私有(文件 ``static`` )程序提供kernel-doc
格式的文档,以确保内核源代码布局的一致性。此建议优先级较低,由内核源文件的
维护者自行决定。

如何格式化kernel-doc注释
------------------------

kernel-doc注释用 ``/**`` 作为开始标记。 ``kernel-doc`` 工具将提取以这种方式
标记的注释。注释其余部分的格式类似于一个普通的多行注释,左侧有一列星号,以
``*/`` 行结束。

函数和类型的kernel-doc注释应该放在所描述的函数或类型之前,以便最大限度地提高
更改代码的人同时更改文档的可能性。概述kernel-doc注释可以放在最顶部的任何地方。

用详细模式和不生成实际输出来运行 ``kernel-doc`` 工具,可以验证文档注释的格式
是否正确。例如::

	scripts/kernel-doc -v -none drivers/foo/bar.c

当请求执行额外的gcc检查时,内核构建将验证文档格式::

	make W=n

函数文档
--------

函数和函数式宏的kernel-doc注释的一般格式是::

  /**
   * 函数名() - 函数简要说明.
   * @参数1: 描述第一个参数.
   * @参数2: 描述第二个参数.
   *        可以为参数提供一段
   *        多行描述.
   *
   * 更详细的描述,进一步讨论函数 函数名(), 这可能对使用或修改它的人有用.
   * 以空注释行开始, 内部可以包含空注释行.
   *
   * 详细描述可以有多个段落.
   *
   * Context: 描述函数是否可以休眠, 它需要、释放或期望持有什么锁.
   *          可以写多行.
   * Return: 描述函数返回值.
   *
   * 返回值描述也可以有多个段落,
   * 并且应该放在注释块的末尾.
   */

函数名后面的简短描述可以跨多行,并以参数描述、空注释行或注释块结尾结束。

函数参数
~~~~~~~~

每个函数参数都应该按照顺序描述,紧跟在函数简要说明之后。不要在函数描述和参数
之间,也不要在参数之间留空。

每个 ``@参数:`` 描述可以跨多行。

.. note::

   如果 ``@参数`` 描述有多行,则说明的续行应该从上一行的同一列开始::

      * @参数: 较长说明
      *        的续行

   或::

      * @参数:
      *		较长说明
      *         的续行

如果函数的参数数目可变,则需用kernel-doc格式对其进行描述::

      * @...: 描述

函数上下文
~~~~~~~~~~

可调用函数的上下文应该在 ``Context`` 节中描述。此节应该包括函数是休眠的还是
可以从中断上下文调用的,以及它需要什么锁、释放什么锁和期望它的调用者持有什么
锁。

例如::

  * Context: Any context.
  * Context: Any context. Takes and releases the RCU lock.
  * Context: Any context. Expects <lock> to be held by caller.
  * Context: Process context. May sleep if @gfp flags permit.
  * Context: Process context. Takes and releases <mutex>.
  * Context: Softirq or process context. Takes and releases <lock>, BH-safe.
  * Context: Interrupt context.

返回值
~~~~~~

如有返回值,应在 ``Return`` 节中描述。

.. note::

  #) 您提供的多行描述文本 *不会* 识别换行符,因此如果您想将某些文本预格式化,
     如::

	* Return:
	* 0 - OK
	* -EINVAL - invalid argument
	* -ENOMEM - out of memory

     它们在最终文档中变成一行::

	Return: 0 - OK -EINVAL - invalid argument -ENOMEM - out of memory

     因此,为了在需要的地方换行,您需要使用ReST列表,例如::

      * Return:
      * * 0		- OK to runtime suspend the device
      * * -EBUSY	- Device should not be runtime suspended

  #) 如果您提供的描述性文本中的行以某个后跟冒号的短语开头,则每一个这种短语
     都将被视为新的节标题,可能会产生意料不到的效果。

结构体、共用体、枚举类型文档
----------------------------

结构体(struct)、共用体(union)、枚举(enum)类型kernel-doc注释的一般格式为::

  /**
   * struct 结构体名 - 简要描述.
   * @成员1: 成员1描述.
   * @成员2: 成员2描述.
   *           可以为成员提供
   *           多行描述.
   *
   * 结构体的描述.
   */

可以用 ``union`` 或 ``enum`` 替换上面示例中的 ``struct`` ,以描述共用体或枚举。
``成员`` 用于表示枚举中的元素或共用体成员。

结构体名称后面的简要说明可以跨多行,并以成员说明、空白注释行或注释块结尾结束。

成员
~~~~

结构体、共用体和枚举的成员应以与函数参数相同的方式记录;它们后紧跟简短的描述,
并且为多行。

在结构体或共用体描述中,可以使用 ``private:`` 和 ``public:`` 注释标签。
``private:`` 域内的字段不会列在生成的文档中。

``private:`` 和 ``public:`` 标签必须紧跟在 ``/*`` 注释标记之后。可以选择是否
在 ``:`` 和 ``*/`` 结束标记之间包含注释。

例子::

  /**
   * struct 张三 - 简短描述
   * @a: 第一个成员
   * @b: 第二个成员
   * @d: 第三个成员
   *
   * 详细描述
   */
  struct 张三 {
      int a;
      int b;
  /* private: 仅内部使用 */
      int c;
  /* public: 下一个是公有的 */
      int d;
  };

嵌套的结构体/共用体
~~~~~~~~~~~~~~~~~~~

嵌套的结构体/共用体可像这样记录::

      /**
       * struct nested_foobar - a struct with nested unions and structs
       * @memb1: first member of anonymous union/anonymous struct
       * @memb2: second member of anonymous union/anonymous struct
       * @memb3: third member of anonymous union/anonymous struct
       * @memb4: fourth member of anonymous union/anonymous struct
       * @bar: non-anonymous union
       * @bar.st1: struct st1 inside @bar
       * @bar.st2: struct st2 inside @bar
       * @bar.st1.memb1: first member of struct st1 on union bar
       * @bar.st1.memb2: second member of struct st1 on union bar
       * @bar.st2.memb1: first member of struct st2 on union bar
       * @bar.st2.memb2: second member of struct st2 on union bar
       */
      struct nested_foobar {
        /* Anonymous union/struct*/
        union {
          struct {
            int memb1;
            int memb2;
          };
          struct {
            void *memb3;
            int memb4;
          };
        };
        union {
          struct {
            int memb1;
            int memb2;
          } st1;
          struct {
            void *memb1;
            int memb2;
          } st2;
        } bar;
      };

.. note::

   #) 在记录嵌套结构体或共用体时,如果结构体/共用体 ``张三`` 已命名,则其中
      的成员 ``李四`` 应记录为 ``@张三.李四:``

   #) 当嵌套结构体/共用体是匿名的时,其中的成员 ``李四`` 应记录为 ``@李四:``

行间注释文档
~~~~~~~~~~~~

结构成员也可在定义时以行间注释形式记录。有两种样式,一种是单行注释,其中开始
``/**`` 和结束 ``*/`` 位于同一行;另一种是多行注释,开头结尾各自位于一行,就
像所有其他核心文档注释一样::

  /**
   * struct 张三 - 简短描述.
   * @张三: 成员张三.
   */
  struct 张三 {
        int 张三;
        /**
         * @李四: 成员李四.
         */
        int 李四;
        /**
         * @王五: 成员王五.
         *
         * 此处,成员描述可以为好几段.
         */
        int 王五;
        union {
                /** @儿子: 单行描述. */
                int 儿子;
        };
        /** @赵六: 描述@张三里面的结构体@赵六 */
        struct {
                /**
                 * @赵六.女儿: 描述@张三.赵六里面的@女儿
                 */
                int 女儿;
        } 赵六;
  };

Typedef文档
-----------

Typedef的kernel-doc文档注释的一般格式为::

  /**
   * typedef 类型名称 - 简短描述.
   *
   * 类型描述.
   */

还可以记录带有函数原型的typedef::

  /**
   * typedef 类型名称 - 简短描述.
   * @参数1: 参数1的描述
   * @参数2: 参数2的描述
   *
   * 类型描述.
   *
   * Context: 锁(Locking)上下文.
   * Return: 返回值的意义.
   */
   typedef void (*类型名称)(struct v4l2_ctrl *参数1, void *参数2);

高亮与交叉引用
--------------

在kernel-doc注释的描述文本中可以识别以下特殊模式,并将其转换为正确的
reStructuredText标记和 `Sphinx C 域`_ 引用。

.. attention:: 以下内容 **仅** 在kernel-doc注释中识别, **不会** 在普通的
               reStructuredText文档中识别。

``funcname()``
  函数引用。

``@parameter``
  函数参数的名称(未交叉引用,仅格式化)。

``%CONST``
  常量的名称(未交叉引用,仅格式化)。

````literal````
  预格式化文本块。输出将使用等距字体。

  若你需要使用在kernel-doc脚本或reStructuredText中有特殊含义的字符,则此功能
  非常有用。

  若你需要在函数描述中使用类似于 ``%ph`` 的东西,这特别有用。

``$ENVVAR``
  环境变量名称(未交叉引用,仅格式化)。

``&struct name``
  结构体引用。

``&enum name``
  枚举引用。

``&typedef name``
  Typedef引用。

``&struct_name->member`` or ``&struct_name.member``
  结构体或共用体成员引用。交叉引用将链接到结构体或共用体定义,而不是直接到成员。

``&name``
  泛类型引用。请首选上面描述的完整引用方式。此法主要是为了可能未描述的注释。

从reStructuredText交叉引用
~~~~~~~~~~~~~~~~~~~~~~~~~~

无需额外的语法来从reStructuredText文档交叉引用kernel-do注释中定义的函数和类型。
只需以 ``()`` 结束函数名,并在类型之前写上 ``struct`` , ``union`` , ``enum``
或 ``typedef`` 。
例如::

  See foo().
  See struct foo.
  See union bar.
  See enum baz.
  See typedef meh.

若要在交叉引用链接中使用自定义文本,可以通过以下语法进行::

  See :c:func:`my custom link text for function foo <foo>`.
  See :c:type:`my custom link text for struct bar <bar>`.

有关更多详细信息,请参阅 `Sphinx C 域`_ 文档。

总述性文档注释
--------------

为了促进源代码和注释紧密联合,可以将kernel-doc文档块作为自由形式的注释,而
不是函数、结构、联合、枚举或typedef的绑定kernel-doc。例如,这可以用于解释
驱动程序或库代码的操作理论。

这是通过使用带有节标题的 ``DOC:`` 节关键字来实现的。

总述或高层级文档注释的一般格式为::

  /**
   * DOC: Theory of Operation
   *
   * The whizbang foobar is a dilly of a gizmo. It can do whatever you
   * want it to do, at any time. It reads your mind. Here's how it works.
   *
   * foo bar splat
   *
   * The only drawback to this gizmo is that is can sometimes damage
   * hardware, software, or its subject(s).
   */

``DOC:`` 后面的标题用作源文件中的标题,但也用作提取文档注释的标识符。因此,
文件中的标题必须是唯一的。

包含kernel-doc注释
==================

文档注释可以被包含在任何使用专用kernel-doc Sphinx指令扩展的reStructuredText
文档中。

kernel-doc指令的格式如下::

  .. kernel-doc:: source
     :option:

*source* 是相对于内核源代码树的源文件路径。
支持以下指令选项:

export: *[source-pattern ...]*
  包括 *source* 中使用 ``EXPORT_SYMBOL`` 或 ``EXPORT_SYMBOL_GPL`` 导出的所有
  函数的文档,无论是在 *source* 中还是在 *source-pattern* 指定的任何文件中。

  当kernel-doc注释被放置在头文件中,而 ``EXPORT_SYMBOL`` 和 ``EXPORT_SYMBOL_GPL``
  位于函数定义旁边时, *source-pattern* 非常有用。

  例子::

    .. kernel-doc:: lib/bitmap.c
       :export:

    .. kernel-doc:: include/net/mac80211.h
       :export: net/mac80211/*.c

internal: *[source-pattern ...]*
  包括 *source* 中所有在 *source* 或 *source-pattern* 的任何文件中都没有使用
  ``EXPORT_SYMBOL`` 或 ``EXPORT_SYMBOL_GPL`` 导出的函数和类型的文档。

  例子::

    .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
       :internal:

identifiers: *[ function/type ...]*
  在 *source* 中包含每个 *function* 和 *type* 的文档。如果没有指定 *function* ,
  则 *source* 中所有函数和类型的文档都将包含在内。

  例子::

    .. kernel-doc:: lib/bitmap.c
       :identifiers: bitmap_parselist bitmap_parselist_user

    .. kernel-doc:: lib/idr.c
       :identifiers:

no-identifiers: *[ function/type ...]*
  排除 *source* 中所有 *function* 和 *type* 的文档。

  例子::

    .. kernel-doc:: lib/bitmap.c
       :no-identifiers: bitmap_parselist

functions: *[ function/type ...]*
  这是“identifiers”指令的别名,已弃用。

doc: *title*
  包含 *source* 中由 *title*  标题标识的 ``DOC:`` 文档段落。 *title* 中允许
  空格;不要在 *title* 上加引号。 *title*  仅用作段落的标识符,不包含在输出中。
  请确保在所附的reStructuredText文档中有适当的标题。

  例子::

    .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
       :doc: High Definition Audio over HDMI and Display Port

如果没有选项,kernel-doc指令将包含源文件中的所有文档注释。

kernel-doc扩展包含在内核源代码树中,位于 ``Documentation/sphinx/kerneldoc.py`` 。
在内部,它使用 ``scripts/kernel-doc`` 脚本从源代码中提取文档注释。

.. _kernel_doc_zh:

如何使用kernel-doc生成手册(man)页
-----------------------------------

如果您只想使用kernel-doc生成手册页,可以从内核git树这样做::

  $ scripts/kernel-doc -man \
    $(git grep -l '/\*\*' -- :^Documentation :^tools) \
    | scripts/split-man.pl /tmp/man

一些旧版本的git不支持路径排除语法的某些变体。
以下命令之一可能适用于这些版本::

  $ scripts/kernel-doc -man \
    $(git grep -l '/\*\*' -- . ':!Documentation' ':!tools') \
    | scripts/split-man.pl /tmp/man

  $ scripts/kernel-doc -man \
    $(git grep -l '/\*\*' -- . ":(exclude)Documentation" ":(exclude)tools") \
    | scripts/split-man.pl /tmp/man