1. 程式人生 > >Linux核心文件:如何寫符合 kernel-doc 規範的註釋

Linux核心文件:如何寫符合 kernel-doc 規範的註釋

## 簡介 Linux核心使用 [Sphinx](http://www.sphinx-doc.org/) 實現把 *Documentation* 目錄下的 [reStructuredText](http://docutils.sourceforge.net/rst.html) 檔案轉換為非常漂亮的文件。文件既可以通過 **make htmldocs** 轉換成 *HTML* 格式,也可以通過 **make pdfdocs** 轉換為 *PDF* 格式。 轉換生成的文件存放於 *Documentation/output* 目錄下。 Linux核心強大的文件功能,除了直接轉換 ```.rst```文件之外,還能從原始碼中汲取API說明,結構體說明等資訊。當然要做到這樣,原始碼的註釋是有一定要求的。而這篇文件,就是介紹如何寫符合 *kernel-doc* 格式要求的註釋。 [英文版原文](https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html),根據個人理解做的翻譯,如果有翻譯錯誤的地方,請告知。 ## 註釋概述 符合 *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 型別的註釋 通常 *struct* ,*union* 和 *enum* 型別的註釋說明是這樣的: ``` /** * 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* 欄位、空行或者```*/```表示結束。 ### 成員 *struct*,*union* 和 *enum* 的成員註釋格式與函式引數的格式一致,他們都需要簡短的描述且支援換行。 在 *struct* 和 *union* 裡面也支援註釋。支援 ```private``` 和 ```public``` 兩種標籤。```private``` 標籤的成員不會呈現到編譯出來的文件上,類似與 *C++* 上的 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和union 如果出現巢狀定義 ```struct```和```union```,可以參考下面的做法: ``` /** * 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語言上結構體的呼叫方式非常相似。 ### 內聯的成員描述 成員的描述除了放在開頭,還可以放在 *struct* 和 *union* 裡面。支援單行或者多行,以```/**```開頭,以```*/```結束。例如: ``` /* * 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:後面的標題用作原始檔中的標題,也用作提取文件註釋的識別符號。因此,標題在檔案中必須是唯