2011年7月28日 星期四

Linux kernel coding style (中)

7. 從單一出口離開function


雖然有些人打死不用goto,但在kernel裡goto還是很好用的,尤其是goto到function最後統一處理些資源回收的工作。另外:

  • 無條件執行的statement容易理解
  • 減少nesting
  • 很容易新增exit point,減少錯誤的機會
  • 幫助compiler作些最佳化處理

int fun(int a)
{
        int result = 0;
        char *buffer = kmalloc(SIZE);

        if (buffer == NULL)
                return -ENOMEM;

        if (condition1) {
                while (loop1) {
                        ...
                }
                result = 1;
                goto out;
        }
        ...
out:
        kfree(buffer);
        return result;
}

8. 註解


寫註解很好,寫太多卻很糟。別註解你的程式如何運作的,要讓你的code一看就知它如何運作。解釋爛code根本是浪費時間。


把註解放在function之前,解釋它要做什麼或是原因。儘量別把註解寫在function中,如果你的function太大需要分段說明,請回頭看看第6章。當然,簡單紀錄或是提醒些注意事項也不要緊,但千萬別太超過。


註解kernel API請參考Documentation/kernel-doc-nano-HOWTO.txt 以及 scripts/kernel-doc


使用 C89 註解形式:/* ... */。多行的註解請用:

/*
  * This is the preferred style for multi-line
  * comments in the Linux kernel source code.
  * Please use it consistently.
  *
  * Description:  A column of asterisks on the left side,
  * with beginning and ending almost-blank lines.
  */

data也需要註解它們該怎麼用。所以在宣告變數的時候,一行只宣告一個變數,這樣才有空間放註解。


9: 略

(本章傳授如何設定emacs以符合coding style,裡面每兩句話還順便酸GNU coding stlye一句。譯者不用emacs,會用emacs的強者應該也不用看本blog...)


10. Kconfig

Kconfig檔案的縮排方式比較不一樣,property都縮排一個tab,但help文字縮排1 tab + 2 space:

config AUDIT
        bool "Auditing support"
        depends on NET
        help
          Enable auditing infrastructure that can be used with another
          kernel subsystem, such as SELinux (which requires this for
          logging of avc messages output).  Does not do system-call
          auditing without CONFIG_AUDITSYSCALL.

還不成熟的feature要加註 EXPERIMENTAL:
config SLUB
        depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
        bool "SLUB (Unqueued Allocator)"
        ...

有危險性的feature要加註警語:
config ADFS_FS_RW
        bool "ADFS write support (DANGEROUS)"
        depends on ADFS_FS
        ...

詳細資訊請看Documentation/kbuild/kconfig-language.txt


11: 資料結構(譯者以為用reference counting會更好)

如果你的資料結構會被多個thread使用,一定要用reference count,這樣才能確保正在使用中的物件不會因為進入sleep state或其他原因而被其他thread清掉。


記住,lock無法取代reference count。lock是用來維護資料的一致,而reference count是管理記憶體的技巧,通常兩者都需要,不應被混淆。


kernel中很多資料結構有兩層reference count,"下層"的reference count紀錄"下層"的使用數量,當"下層"規零時,才會影響"上層"的reference count。請參考記憶體管理 ("struct mm_struct": mm_users and mm_count)和檔案系統
("struct super_block": s_count and s_active)相關的程式碼。


12. Macros, Enums and RTL

用來定義常數的 macro 或 enum 用全大寫。

#define CONSTANT 0x12345

用來模擬function的macro則為全小寫。不過用inline function更好。包含多個statement的macro需以do...while包覆:

#define macrofun(a, b, c)               \
        do {                            \
                if (a == 5)             \
                do_this(b, c);          \
        } while (0)

其他注意事項:

  • macro不要影響到control flow,例如在macro內使用return。
  • macro不要使用外面的local variable
  • 不要把macro用在l-valie:FOO(x) = y;
  • 定義常數的macro若有運算子,需以括號包起來。
    #define CONSTANT 0x4000
    #define CONSTEXP (CONSTANT | 3)
    

沒有留言:

張貼留言