热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Linux内核文档:如何写符合kerneldoc规范的注释

Linux内核强大的文档功能,除了直接转换```.rst```文档之外,还能从源码中汲取API说明,结构体说明等信息。当然要做到这样,源码的注释是有一定要求的。而这篇文档,就是介绍
Linux内核强大的文档功能,除了直接转换 ```.rst```文档之外,还能从源码中汲取API说明,结构体说明等信息。当然要做到这样,源码的注释是有一定要求的。而这篇文档,就是介绍如何写符合 *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  to be held by caller.
* Context: Process context. May sleep if @gfp flags permit.
* Context: Process context. Takes and releases .
* Context: Softirq or process context. Takes and releases , 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:后面的标题用作源文件中的标题,也用作提取文档注释的标识符。因此,标题在文件中必须是唯一的。


推荐阅读
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • centos 7.0 lnmp成功安装过程(很乱)
    下载nginx[rootlocalhostsrc]#wgethttp:nginx.orgdownloadnginx-1.7.9.tar.gz--2015-01-2412:55:2 ... [详细]
  • C语言是计算机科学和编程领域的基石,许多初学者在学习过程中会感到困惑。本文将详细介绍C语言的基本概念、关键语法和实用示例,帮助你快速上手C语言。 ... [详细]
  • 从零开始编译Linux系统:第16章 全新起点
    本章将详细介绍如何从零开始编译一套完整的Linux系统,涵盖关键组件如glibc库的介绍及其重要性。通过本文,读者将了解从源代码构建Linux系统的全过程。 ... [详细]
  • 解决Jenkins编译过程中ERROR: Failed to Parse POMs的问题
    在使用Jenkins进行自动化构建时,有时会遇到“ERROR: Failed to parse POMs”的错误。本文将详细分析该问题的原因,并提供有效的解决方案。 ... [详细]
  • 阿里云 Aliplayer高级功能介绍(八):安全播放
    如何保障视频内容的安全,不被盗链、非法下载和传播,阿里云视频点播已经有一套完善的机 ... [详细]
  • Bootstrap 插件使用指南
    本文详细介绍了如何在 Web 前端开发中使用 Bootstrap 插件,包括自动触发插件的方法、插件的引用方式以及具体的实例。 ... [详细]
  • 使用HTML和JavaScript实现视频截图功能
    本文介绍了如何利用HTML和JavaScript实现从远程MP4、本地摄像头及本地上传的MP4文件中截取视频帧,并展示了具体的实现步骤和示例代码。 ... [详细]
  • 本文详细介绍了 Java 网站开发的相关资源和步骤,包括常用网站、开发环境和框架选择。 ... [详细]
  • 本文介绍了 Go 语言中的高性能、可扩展、轻量级 Web 框架 Echo。Echo 框架简单易用,仅需几行代码即可启动一个高性能 HTTP 服务。 ... [详细]
  • 本文详细介绍如何使用Netzob工具逆向未知通信协议,涵盖从基本安装到高级模糊测试的全过程。通过实例演示,帮助读者掌握Netzob的核心功能。 ... [详细]
  • 本文介绍了Java编程语言的基础知识,包括其历史背景、主要特性以及如何安装和配置JDK。此外,还详细讲解了如何编写和运行第一个Java程序,并简要介绍了Eclipse集成开发环境的安装和使用。 ... [详细]
  • 本文将介绍如何在混合开发(Hybrid)应用中实现Native与HTML5的交互,包括基本概念、学习目标以及具体的实现步骤。 ... [详细]
  • 为什么多数程序员难以成为架构师?
    探讨80%的程序员为何难以晋升为架构师,涉及技术深度、经验积累和综合能力等方面。本文将详细解析Tomcat的配置和服务组件,帮助读者理解其内部机制。 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
author-avatar
mobiledu2502896807
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有