• Linux内核文档:如何写符合 kernel-doc 规范的注释


    简介

    Linux内核使用 Sphinx 实现把 Documentation 目录下的 reStructuredText 文件转换为非常漂亮的文档。文档既可以通过 make htmldocs 转换成 HTML 格式,也可以通过 make pdfdocs 转换为 PDF 格式。 转换生成的文档存放于 Documentation/output 目录下。

    Linux内核强大的文档功能,除了直接转换 .rst文档之外,还能从源码中汲取API说明,结构体说明等信息。当然要做到这样,源码的注释是有一定要求的。而这篇文档,就是介绍如何写符合 kernel-doc 格式要求的注释。

    英文版原文,根据个人理解做的翻译,如果有翻译错误的地方,请告知。

    注释概述

    符合 kernel-doc 的注释,都需要从 /** 开始,其后每一行内容都以 *开头,最后是 */ 表示结束。例如:

    /**
     * This is a sample of comment
     */
    

    对于函数和类型的注释,必须放在函数和类型之前,以便于别人在修改代码的时候,可以顺手把注释也改了。对概述类型的注释,可以放到文件顶部的位置。

    Linux内核有提供一个工具用于对 kernel-doc 的格式进行检查,例如:

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

    当然,在编译的时候,如果添加以下的选项,也会检查文档的格式:

    make W=n
    

    函数文档

    规范的格式示例如下:

    /**
     * function_name() - Brief description of function.
     * @arg1: Describe the first argument.
     * @arg2: Describe the second argument.
     *        One can provide multiple line descriptions
     *        for arguments.
     *
     * A longer description, with more discussion of the function function_name()
     * that might be useful to those using or modifying it. Begins with an
     * empty comment line, and may include additional embedded empty
     * comment lines.
     *
     * The longer description may have multiple paragraphs.
     *
     * Context: Describes whether the function can sleep, what locks it takes,
     *          releases, or expects to be held. It can extend over multiple
     *          lines.
     * Return: Describe the return value of function_name.
     *
     * The return value description can also have multiple paragraphs, and should
     * be placed at the end of the comment block.
     */
    

    函数名后的函数功能简介可以跨越多行,以函数参数描述、返回值描述或其他描述结束。

    函数参数

    函数参数的描述,必须直接且按顺序放在函数简介之后。需要注意的是,函数参数与函数简介、函数参数与函数参数之间不能有任何空行。

    每个函数参数的描述可以跨行,但要注意的是,必须保持缩进对齐,例如

    * @argument: some long description
    *            that continues on next lines   # that 必须与 some对齐(避免排版乱套,补充说明)
    

    或者

    * @argument:
    *         some long description
    *         that continues on next lines
    

    函数参数

    如果出现不定数量个参数,可以这么表示:

    * @...: description
    

    函数上下文

    描述这个函数会在什么场景下调用,就是函数上下文字段所要做的。函数上下文字段用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:字段。

    由于不能识别换行,因此如果你这样写:

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

    效果只会是:

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

    所以呢,如果你要换行,你需要使用 ReST List,例如:

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

    另外,如果字段出现类似key:这样短语加冒号的形式,会被识别为其他的字段。这点需要注意。

    struct 和 union 和 enum 类型的注释

    通常 structunionenum 类型的注释说明是这样的:

    /**
     * struct struct_name - Brief description.
     * @member1: Description of member1.
     * @member2: Description of member2.
     *           One can provide multiple line descriptions
     *           for members.
     *
     * Description of the structure.
     */
    

    紧随名字后面的 Brief description 可以跨度几行,它以 @member 字段、空行或者*/表示结束。

    成员

    structunionenum 的成员注释格式与函数参数的格式一致,他们都需要简短的描述且支持换行。

    structunion 里面也支持注释。支持 privatepublic 两种标签。private 标签的成员不会呈现到编译出来的文档上,类似与 C++ 上的 private 成员。

    需要注意的是,privatepublic 标签必须以*标识开始且不能有缩进,以*/标识结束。如果有简介,可以写在:与结束标识*/之间,例如:

    /**
     * struct my_struct - short description
     * @a: first member
     * @b: second member
     * @d: fourth member
     *
     * Longer description
     */
    struct my_struct {
        int a;
        int b;
    /* private: internal use only */
        int c;
    /* public: the next one is public */
        int d;
    };
    

    嵌套struct和union

    如果出现嵌套定义 structunion,可以参考下面的做法:

    /**
     * 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;
    };
    

    有两点要注意的:

    1. 如果嵌套的struct或者union有命名,那么应该使用@foo.bar的形式,例如上例的@bar.st1
    2. 如果是匿名的,那么需要直接使用@bar的形式,例如上例的@memb1

    细心的小伙伴可能发现,这与C语言上结构体的调用方式非常相似。

    内联的成员描述

    成员的描述除了放在开头,还可以放在 structunion 里面。支持单行或者多行,以/**开头,以*/结束。例如:

    /*
     * struct foo - Brief description.
     * @foo: The Foo member.
     */
    struct foo {
          int foo;
          /**
           * @bar: The Bar member.
           */
          int bar;
          /**
           * @baz: The Baz member.
           *
           * Here, the member description may contain several paragraphs.
           */
          int baz;
          union {
                  /** @foobar: Single line description. */
                  int foobar;
          };
          /** @bar2: Description for struct @bar2 inside @foo */
          struct {
                  /**
                   * @bar2.barbar: Description for @barbar inside @foo.bar2
                   */
                  int barbar;
          } bar2;
    };
    

    typedef注释

    通常格式如下:

    /**
     * typedef type_name - Brief description.
     *
     * Description of the type.
     */
    

    如果是函数的类型定义,也可以这样:

    /**
     * typedef type_name - Brief description.
     * @arg1: description of arg1
     * @arg2: description of arg2
     *
     * Description of the type.
     *
     * Context: Locking context.
     * Return: Meaning of the return value.
     */
     typedef void (*type_name)(struct v4l2_ctrl *arg1, void *arg2);
    

    高亮和交叉索引

    在各种说明字段中,可以用以下的形式做成索引。

    funcname()

    索引到函数
    

    @parameter

    索引到函数参数(只在本函数内索引,不会交叉到其他函数)
    

    %CONST

    索引到指定名字的上下文段说明(只在本函数内索引,不会交叉到其他函数)
    

    ``literal``

    字面意义,让 kernel-doc 不解析,做纯字符串处理。常用于出现与 kernel-doc 或者 reStructuredText 关键字冲突的情况
    

    $ENVVAR

    环境变量(只在本函数内索引,不会交叉到其他函数)
    

    &struct name

    索引到其他结构体
    

    &enum name

    索引到其他的枚举型
    

    &typedef name

    索引到typedef定义的类型
    

    &struct_name->member or &struct_name.member

    索引到制定结构体成员
    

    &name

    泛型类型引用。不建议使用,请使用其他方法
    

    概述说明

    为了便于将源代码和注释紧密结合在一起,可以包含自由格式注释的内核文档块,而不是函数、结构、联合、枚举或typedef的内核文档块。例如,这可以用于驱动程序或库代码的操作理论。

    这是通过使用带有节标题的DOC:section关键字来完成的。

    通用的格式如下:

    /**
     * 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:后面的标题用作源文件中的标题,也用作提取文档注释的标识符。因此,标题在文件中必须是唯一的。

  • 相关阅读:
    MySQL之汇总数据(AVG,COUNT,MAX,MIN,SUM)
    查询两门及两门以上不及格同学的平均分
    百度乐播音乐真实地址查找api接口
    腾讯云服务器无法ssh登陆问题
    ubuntu搭建php运行环境
    阿里云腾讯云服务器ubuntu多域名配置
    PHP 快速排序算法详解
    PHP7.x新特性
    PHP的钩子实现解析
    PHP 二维数组根据某个字段排序 复制代码 array_multisort
  • 原文地址:https://www.cnblogs.com/gmpy/p/12529456.html
Copyright © 2020-2023  润新知