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:后面的標題用作源文件中的標題,也用作提取文檔注釋的標識符。因此,標題在文件中必須是唯一的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM