1 .. SPDX-License-Identifier: GPL-2.0 2 3 .. include:: ../disclaimer-zh_TW.rst 4 5 :Original: :ref:`Documentation/process/4.Codin 6 7 :Translator: 8 9 時奎亮 Alex Shi <alex.shi@linux.alibaba.com 10 11 :校譯: 12 13 吳想成 Wu XiangCheng <bobwxc@email.cn> 14 胡皓文 Hu Haowen <2023002089@link.tyut.edu. 15 16 .. _tw_development_coding: 17 18 使代碼正確 19 ====================== 20 21 雖然一個堅實的、面向社區的設計 22 的證明都反映在代碼中。它是將由 23 的代碼。所以這段代碼的質量決定 24 25 本節將檢查編碼過程。我們將從內 26 到正確的做法和相關有用的工具上 27 28 陷阱 29 ---- 30 31 代碼風格 32 ******** 33 34 內核長期以來都有其標準的代碼風 35 :ref:`Documentation/translations/zh_CN/process 36 中所述。在多數時候,該文檔中描 37 大量不符合代碼風格準則的代碼。 38 39 首先,相信內核代碼標準並不重要 40 編寫代碼,那麼新代碼將很難加入 41 對代碼進行重新格式化。一個像內 42 開發人員能夠快速理解其中的任何 43 44 內核的代碼風格偶爾會與僱主的強 45 之前遵從內核代碼風格。將代碼放 46 包括控制代碼樣式。 47 48 另一個危害是認爲已經在內核中的 49 重新格式化補丁,作爲熟悉開發過 50 的一種方式,或者兩者兼而有之。 51 往受到冷遇。因此,最好避免編寫 52 同時順帶修復其樣式是很自然的, 53 54 代碼風格文檔也不應該被視爲絕對 55 樣式(例如爲了80列限制拆分行會 56 57 注意您還可以使用 ``clang-format`` 工 58 化部分代碼,和審閱完整的文件以 59 可以方便地排序 ``#includes`` 、對齊 60 信息,請參閱文檔 :ref:`Documentation/d 61 62 抽象層 63 ****** 64 65 計算機科學教授教學生以靈活性和 66 地使用了抽象;任何涉及數百萬行 67 表明,過度或過早的抽象可能和過 68 不要過度。 69 70 簡單點,先考慮一個調用時始終只 71 以在需要使用它時提供的額外靈活 72 可能以某種從未被注意到的微妙方 73 的靈活性時,它並未以符合程序員 74 補丁來刪除未使用的參數;一般來 75 76 隱藏硬件訪問的抽象層——通常爲 77 歡迎。這樣的層使代碼變得模糊, 78 79 另一方面,如果您發現自己從另一 80 瞭解一下:是否需要將這些代碼中 81 實現這些功能。在整個內核中複製 82 83 #ifdef 和預處理 84 *************** 85 86 C預處理器似乎給一些C程序員帶來 87 源代碼中的方法。但是預處理器不 88 對編譯器來說更難檢查正確性。使 89 清理工作的標誌。 90 91 使用#ifdef的條件編譯實際上是一個 92 看到代碼被鋪滿#ifdef塊。一般規定 93 編譯代碼可以限制函數,如果代碼 94 悄悄地優化對空函數的調用。使得 95 96 C預處理器宏存在許多危險性,包括 97 重評估。如果您試圖定義宏,請考 98 函數更容易閱讀,不會多次計算其 99 100 內聯函數 101 ******** 102 103 不過,內聯函數本身也存在風險。 104 文件所固有的效率。然而,這些功 105 點都被複制一遍,所以最終會增加 106 造成壓力,從而大大降低執行速度 107 函數調用的成本並不高;大量創建 108 109 一般來說,內核程序員會自冒風險 110 時間/空間權衡通常不適用於當代硬 111 更緊湊的程序運行得慢。 112 113 較新的編譯器越來越激進地決定一 114 “inline”關鍵字可能不僅僅是過度 115 116 鎖 117 ** 118 119 2006年5月,“deviceescape”網絡堆棧 120 這是一個受歡迎的消息;Linux中對 121 Deviceescape堆棧承諾修復這種情況。 122 正進入主線。發生了什麼? 123 124 這段代碼出現了許多閉門造車的跡 125 設計。在合併這個網絡堆棧(現在 126 改造。 127 128 曾經,Linux內核代碼可以在不考慮 129 開發。然而現在,這個文檔就是在 130 爲提高響應能力所做的工作也會提 131 的日子早已遠去。 132 133 可以由多個線程併發訪問的任何資 134 的代碼應該謹記這一要求;事後修 135 時間充分了解可用的鎖原語,以便 136 很難進入主線。 137 138 迴歸 139 **** 140 141 最後一個值得一提的危險是迴歸: 142 (這也可能會帶來很大的改進)。 143 最不受歡迎的問題。除了少數例外 144 將被取消。最好首先避免迴歸發生 145 146 人們常常爭論,如果迴歸帶來的功 147 如果它破壞了一個系統卻爲十個系 148 Linus對這個問題給出了最佳答案: 149 150 :: 151 152 所以我們不會通過引入新問 153 是否真的有進展。是前進兩 154 155 (http://lwn.net/Articles/243460/) 156 157 特別不受歡迎的一種迴歸類型是用 158 就必須無限期地支持它。這一事實 159 不能以不兼容的方式進行更改,所 160 的思考、清晰的文檔和廣泛的審查 161 162 163 代碼檢查工具 164 ------------ 165 166 至少目前,編寫無錯誤代碼仍然是 167 的是,在代碼進入主線內核之前, 168 員已經提供了一系列令人印象深刻 169 發現的任何問題都是一個以後不會 170 自動化工具。 171 172 第一步是注意編譯器產生的警告。 173 通常,這些警告都指向真正的問題 174 在消除警告時,注意瞭解真正的原 175 176 請注意,並非所有編譯器警告都默 177 獲得完整集合。 178 179 內核提供了幾個配置選項,可以打 180 子菜單中。對於任何用於開發或測 181 您應該打開: 182 183 - FRAME_WARN 獲取大於給定數量的堆 184 這些警告生成的輸出可能比較冗 185 186 - DEBUG_OBJECTS 將添加代碼以跟蹤內 187 時發出警告。如果你要添加創建 188 考慮打開對象調試基礎結構的支 189 190 - DEBUG_SLAB 可以發現各種內存分配 191 192 - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP 和 DEBU 193 鎖錯誤。 194 195 還有很多其他調試選項,其中一些 196 一直使用。在學習可用選項上花費 197 198 其中一個較重的調試工具是鎖檢查 199 (spinlock或mutex)的獲取和釋放、獲 200 它可以確保總是以相同的順序獲取 201 說,lockdep可以找到許多導致系統死 202 很痛苦(對於開發人員和用戶而言 203 任何類型的非普通鎖的代碼在提交 204 205 作爲一個勤奮的內核程序員,毫無 206 的返回狀態。然而,事實上,最終 207 代碼往往會出問題;如果所有這些 208 更有信心。 209 210 內核提供了一個可以做到這一點的 211 啓用故障注入後,內存分配的可配 212 範圍內。在啓用了故障注入的情況 213 應。有關如何使用此工具的詳細信 214 Documentation/fault-injection/fault-injection. 215 216 “sparse”靜態分析工具可以發現其 217 和內核空間地址之間的混淆、大端 218 整數值等等。sparse必須單獨安裝(如 219 可以在 https://sparse.wiki.kernel.org/index 220 然後可以通過在make命令中添加“C=1 221 222 “Coccinelle”工具 :ref:`http://coccinelle 223 能夠發現各種潛在的編碼問題;它 224 scripts/coccinelle目錄下已經打包了相 225 “make coccicheck”將運行這些語義補 226 :ref:`Documentation/dev-tools/coccinelle.rst < 227 228 229 其他類型的可移植性錯誤最好通過 230 或Blackfin開發板,您仍然可以執行 231 交叉編譯器: 232 233 https://www.kernel.org/pub/tools/cross 234 235 花一些時間安裝和使用這些編譯器 236 237 文檔 238 ---- 239 240 文檔通常比內核開發規則更爲例外 241 到內核中的過程,使其他開發人員 242 下,添加文檔已基本上是強制性的 243 244 任何補丁的第一個文檔是其關聯的 245 方案的形式、處理補丁的人員、對 246 其他內容。確保變更日誌說明了*爲 247 248 任何添加新用戶空間接口的代碼— 249 的文檔,該文檔使用戶空間開發人 250 Documentation/ABI/README,瞭解如何此文 251 252 文檔 :ref:`Documentation/admin-guide/kernel- 253 描述了內核的所有引導時間參數。 254 條目。 255 256 任何新的配置選項都必須附有幫助 257 希望何時使用它們。 258 259 許多子系統的內部API信息通過專門 260 “kernel-doc”腳本以多種方式提取和 261 工作,則應該維護它們,並根據需 262 的領域中,爲將來添加kerneldoc註釋 263 來說是一個有用的活動。這些註釋 264 :ref:`Documentation/doc-guide/ <doc_guide>` 265 266 任何閱讀大量現有內核代碼的人都 267 對新代碼的要求比過去更高;合併 268 詳細註釋的代碼。代碼本身應該是 269 270 某些事情應該總是被註釋。使用內 271 屏障。數據結構的鎖規則通常需要 272 的文檔。應該指出代碼中分立的位 273 錯誤的“清理”的事情都需要一個 274 275 276 內部API更改 277 ----------- 278 279 內核提供給用戶空間的二進制接口 280 是高度流動的,當需要時可以更改 281 僅因爲它不滿足你的需求導致無法 282 作爲內核開發人員,您有權進行此 283 284 的確可以進行API更改,但更改必須 285 附帶關於更改內容和必要原因的描 286 埋在一個更大的補丁中。 287 288 另一個要點是,更改內部API的開發 289 對於一個廣泛使用的函數,這個責 290 開發人員正在做的工作相沖突。不 291 可靠的。請注意,coccinelle工具可以 292 293 在進行不兼容的API更改時,應儘可 294 到該接口的樹內用處。它還將警告 295 代碼不是內核開發人員需要擔心的 296 的困難。 297
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.