編寫 kernel-doc 註釋¶
Linux 核心原始檔可能包含 kernel-doc 格式的結構化文件註釋,用於描述程式碼的函式、型別和設計。當文件嵌入在原始檔中時,更容易保持文件的更新。
注意
由於歷史原因,kernel-doc 格式表面上與 javadoc、gtk-doc 或 Doxygen 相似,但又截然不同。核心原始碼包含數萬條 kernel-doc 註釋。請堅持此處描述的風格。
注意
kernel-doc 不涵蓋 Rust 程式碼:請參閱 通用資訊。
kernel-doc 結構從註釋中提取,並從中生成帶有錨點的適當的 Sphinx C Domain 函式和型別描述。這些描述會過濾掉特殊的 kernel-doc 高亮顯示和交叉引用。詳見下文。
每個使用 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 註釋的一般格式是
/**
* 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: 描述可以跨越多行。
注意
如果 @argument 描述有多行,則描述的延續應從與前一行相同的列開始
* @argument: some long description
* that continues on next lines
或
* @argument:
* some long description
* that continues on next lines
如果函式有可變數量的引數,則應以 kernel-doc 表示法將其描述為
* @...: 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(或 Returns)的專用部分中描述。
注意
您提供的多行描述性文字不識別換行符,因此如果您嘗試很好地格式化一些文字,如
* 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
如果您提供的描述性文字的行以短語開頭,後跟冒號,則每個短語都將被視為新的節標題,這可能不會產生所需的效果。
結構體、聯合體和列舉文件¶
結構體、聯合體和列舉 kernel-doc 註釋的一般格式是
/**
* 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.
*/
您可以將上述示例中的 struct 替換為 union 或 enum 來描述聯合體或列舉。member 用於表示結構體和聯合體成員名稱以及列舉中的列舉。
結構體名稱後面的簡短描述可以跨越多行,並以成員描述、空白註釋行或註釋塊的結尾結束。
成員¶
結構體、聯合體和列舉的成員應以與函式引數相同的方式記錄;它們緊隨簡短描述之後,並且可以是多行的。
在結構體或聯合體描述中,您可以使用 private: 和 public: 註釋標記。位於 private: 區域內的結構體欄位不會在生成的輸出文件中列出。
private: 和 public: 標記必須緊跟在 /* 註釋標記之後開始。它們可以選擇在 : 和結尾的 */ 標記之間包含註釋。
示例
/**
* 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 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;
};
注意
當記錄巢狀的結構體或聯合體時,如果結構體/聯合體
foo已命名,則其中的成員bar應記錄為@foo.bar:當巢狀的結構體/聯合體是匿名的時,其中的成員
bar應記錄為@bar:
行內成員文件註釋¶
結構體成員也可以在定義中以內聯方式記錄。有兩種樣式,單行註釋,其中開頭 /** 和結尾 */ 都在同一行上,以及多行註釋,其中它們各自位於自己的行上,就像所有其他 kernel-doc 註釋一樣
/**
* 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 kernel-doc 註釋的一般格式是
/**
* typedef type_name - Brief description.
*
* Description of the type.
*/
也可以記錄帶有函式原型的 Typedef
/**
* typedef type_name - Brief description.
* @arg1: description of arg1
* @arg2: description of arg2
*
* Description of the type.
*
* Context: Locking context.
* Returns: Meaning of the return value.
*/
typedef void (*type_name)(struct v4l2_ctrl *arg1, void *arg2);
類物件宏文件¶
類物件宏與類函式宏不同。它們的區別在於宏名稱是否緊跟一個左括號('(')表示類函式宏,而類物件宏則不跟括號。
scripts/kernel-doc 將類函式宏像函式一樣處理。它們可以有一個引數列表。類物件宏沒有引數列表。
類物件宏 kernel-doc 註釋的一般格式是
/**
* define object_name - Brief description.
*
* Description of the object.
*/
示例
/**
* define MAX_ERRNO - maximum errno value that is supported
*
* Kernel pointers have redundant information, so we can use a
* scheme where we can return either an error code or a normal
* pointer with the same return value.
*/
#define MAX_ERRNO 4095
示例
/**
* define DRM_GEM_VRAM_PLANE_HELPER_FUNCS - \
* Initializes struct drm_plane_helper_funcs for VRAM handling
*
* This macro initializes struct drm_plane_helper_funcs to use the
* respective helper functions.
*/
#define DRM_GEM_VRAM_PLANE_HELPER_FUNCS \
.prepare_fb = drm_gem_vram_plane_helper_prepare_fb, \
.cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb
高亮顯示和交叉引用¶
以下特殊模式在 kernel-doc 註釋描述性文字中被識別,並轉換為適當的 reStructuredText 標記和 Sphinx C Domain 引用。
注意
以下內容僅在 kernel-doc 註釋中識別,不在普通的 reStructuredText 文件中識別。
funcname()函式引用。
@parameter函式引數的名稱。(沒有交叉引用,只有格式化。)
%CONST常量的名稱。(沒有交叉引用,只有格式化。)
``literal``應按原樣處理的文字塊。輸出將使用
等寬字型。如果您需要使用特殊字元,否則這些字元會被 kernel-doc 指令碼或 reStructuredText 解釋,這將非常有用。
如果您需要在函式描述中使用類似
%ph的內容,這將特別有用。$ENVVAR環境變數的名稱。(沒有交叉引用,只有格式化。)
&struct name結構體引用。
&enum name列舉引用。
&typedef nameTypedef 引用。
&struct_name->member或&struct_name.member結構體或聯合體成員引用。交叉引用將指向結構體或聯合體定義,而不是直接指向成員。
&name通用型別引用。最好使用上面描述的完整引用。這主要用於遺留註釋。
從 reStructuredText 交叉引用¶
無需額外的語法即可從 reStructuredText 文件交叉引用 kernel-doc 註釋中定義的函式和型別。只需在函式名稱後新增 (),並在型別之前寫 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 Domain 文件。
概述文件註釋¶
為了便於將原始碼和註釋放在一起,您可以包含 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 註釋已放置在標頭檔案中時,source-pattern 非常有用,而
EXPORT_SYMBOL和EXPORT_SYMBOL_GPL位於函式定義旁邊。示例
.. kernel-doc:: lib/bitmap.c :export: .. kernel-doc:: include/net/mac80211.h :export: net/mac80211/*.c
- internal: [source-pattern ...]
包含 source 中所有函式和型別的文件,這些函式和型別未使用
EXPORT_SYMBOL或EXPORT_SYMBOL_GPL在 source 中或在 source-pattern 指定的任何檔案中匯出。示例
.. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c :internal:
- identifiers: [ function/type ...]
包含 source 中每個 function 和 type 的文件。如果未指定 function,則將包含 source 中所有函式和型別的文件。type 可以是結構體、聯合體、列舉或 typedef 識別符號。
示例
.. 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 生成 man 手冊頁¶
如果您只想使用 kernel-doc 生成 man 手冊頁,您可以從核心 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