Chapter 11: Data structures
第11章: 資料結構
Data structures that have visibility outside the single-threaded environment they are created and destroyed in should always have reference counts. In the kernel, garbage collection doesn't exist (and outside the kernel garbage collection is slow and inefficient), which means that you absolutely _have_ to reference count all your uses.
資料結構有一個明顯的外表是為單一執行緒的環境,它的建立與刪除總是使用參考計數。在核心層裡,垃圾收集並不存在 (在核心層以外,垃圾收集是又慢又沒效率的東西) 。
Reference counting means that you can avoid locking, and allows multiple users to have access to the data structure in parallel - and not having to worry about the structure suddenly going away from under them just because they slept or did something else for a while.
參考計數意謂著能夠避免用加鎖,並且允許多個使用者能夠同時的存取它-亦不用擔心結構會忽然的離開,在它睡眠或隔一段時間做其他事時的情況下。
Note that locking is _not_ a replacement for reference counting.
Locking is used to keep data structures coherent, while reference counting is a memory management technique. Usually both are needed, and they are not to be confused with each other.
注意,加鎖並 _不是_ 參考計數的替代物。加鎖用於保持資料結構的一致性,而參考計數是一個記憶体管理技術。通常你兩個都需要,不應該有任何混淆不清的地方。
Many data structures can indeed have two levels of reference counting, when there are users of different "classes". The subclass count counts the number of subclass users, and decrements the global count just once when the subclass count goes to zero.
當有多個不同層級的使用者時,許多的資料結構能夠確實的使用兩層的參考計數。子層級計數 會計數子層級使用者的數量,並且當子層級計數為零時,全域計數會減一。
Examples of this kind of "multi-level-reference-counting" can be found in memory management ("struct mm_struct": mm_users and mm_count), and in filesystem code ("struct super_block": s_count and s_active).
這種 "多層的參考計數" 的例子可以在記憶体管理 ("struct mm_struct"︰mm_users和mm_cout) 和檔案管理 ("struct super_block"︰s_count和s_active) 中找到。
Remember: if another thread can find your data structure, and you don't have a reference count on it, you almost certainly have a bug.
記住︰如果其他的執行緒能夠看見你的資料結構,而你卻沒有對它使用參考計數,那麼幾乎可以肯定你的程式裡會有bug存在。
Chapter 12: Macros, Enums and RTL
第12章: 巨集,列舉和RTL
Names of macros defining constants and labels in enums are capitalized.
用來定義常數的巨集名稱及enum中的元素名稱通常都以大寫的形式出現。
#define CONSTANT 0x12345
Enums are preferred when defining several related constants.
當要定義數個相關聯的常數時,使用enum比使用巨集的方式還要好。
CAPITALIZED macro names are appreciated but macros resembling functions may be named in lower case.
推薦使用大寫巨集名,但功能類似函式的巨集也可以使用小寫。
Generally, inline functions are preferable to macros resembling functions.
通常來講,我們推薦使用inline函式來代替類似函式的巨集。
Macros with multiple statements should be enclosed in a do - while block:
有多行語句的巨集應該包含在一個do-while區塊內︰
#define macrofun(a, b, c) \
do { \
if (a == 5) \
do_this(b, c); \
} while (0)
Things to avoid when using macros:
當使用巨集時應該避免以下幾種情況:
1) macros that affect control flow:
1)避免會影響程式流程的巨集:
#define FOO(x) \
do { \
if (blah(x) < 0) \
return -EBUGGERED; \
} while(0)
is a _very_ bad idea. It looks like a function call but exits the "calling" function; don't break the internal parsers of those who will read the code.
上述寫法 _極_ 差,因為看起來像一個函式被呼叫,但是此函式的返回點卻不是呼叫它的地方;因此,永遠不要在巨集中打斷原有函式的執行。
2) macros that depend on having a local variable with a magic name:
2)避免使用局部變數或難以理解名稱的巨集:
#define FOO(val) bar(index, val)
might look like a good thing, but it's confusing as hell when one reads the code and it's prone to breakage from seemingly innocent changes.
看似好方法,但會讓其他閱讀的人感到困惑,也有可能你不經意間的一個更動也會使程式流程產生錯誤。
3) macros with arguments that are used as l-values: FOO(x) = y; will bite you if somebody e.g. turns FOO into an inline function.
3)避免以左值模式使用帶參數的巨集︰ FOO(x) = y; 如果像上面這樣定義了一個巨集,一旦有人想要將FOO轉成一個inline函式,麻煩就來了。
4) forgetting about precedence: macros defining constants using expressions must enclose the expression in parentheses. Beware of similar issues with macros using parameters.
4)避免忘記運算優先級的巨集︰以巨集定義好的常數來定義其他運算式時,此運算式應該包在括號內。巨集的參數同樣如此。
#define CONSTANT 0x4000
#define CONSTEXP (CONSTANT | 3)
The cpp manual deals with macros exhaustively. The gcc internals manual also covers RTL which is used frequently with assembly language in the kernel.
cpp的手冊中包含有使用巨集應該注意的所有知識,gcc的手冊同樣包含核心中經常與彙編一起使用的RTL方面的知識。
留言列表