歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> 深入學習Linux系統,Linux內核編程風格

深入學習Linux系統,Linux內核編程風格

日期:2017/2/27 9:30:56   编辑:Linux內核
  這篇短小的文檔用於描述Linux內核編程中推薦的編程風格。編程風格是很個人  化的東西,我不想把我的觀點_強加_給任何人,但這是我必須維護的代碼中所遵守  的,我也建議其他部分的代碼也能遵守它。請至少給這裡的觀點一些考慮。    首先,我建議你打印一份GNU代碼風格,不是去讀它,而是把它燒了,這是個很  不錯的姿態。    下面就是Linux內核編程風格:    第一章:縮進  制表符(tabs)占8個字符,所以縮進也是8個字符。有些異端運動想使用4個字符  (甚至是2個字符)的縮進,這和把PI(圓周率)定為3沒什麼兩樣。    原因:縮進的根本目的是用來清晰地標識一個控制塊的起始。特別是當你連續盯  著屏幕看了20 個小時後,你就會體會到更長的縮進的好處了。    現在,有些人提出8字符縮進會使得代碼太偏向右邊,當使用80字符的終端  時很難閱讀。答案是如果你需要三層以上的縮進,那麼你已經完蛋了,應該改改  你的程序了。    簡而言之,8字符縮進使得閱讀代碼更為容易,並且在你的縮進層次過深時提出  警告。應該留心這樣的警告。  關於這一點,我不能苟同,4個字符的縮進確實有它的好處,縮進太多反而看著累。  而且有時候僅僅兩層嵌套就會使代碼很長。    第二章:括號的位置  括號位置的問題在C編程風格中經常被提出。和縮進大小不同,括號位置的選擇  並沒有太多技術上的原因,而更多的是個人的喜好。比如Kernighan和Ritchie的  弟子們把左括號放在一行的最後,把右括號放在一行的開始,象這樣:    if (x is true) {  we do y  }    但是,函數是一種特殊的情況,函數的左括號放在下一行的開始,象這樣:    int function(int x)  {  body of function  }    全世界的異端人士指出這種不一致的做法 ...嗯... 不太一致,但是所有思維正  確的人知道 (a) K&R是_對_的 (b) K&R是對的。而且,函數確實是特殊的(你在C  中無法對函數進行嵌套)。    注意到右括號完全占有單獨的一行,_除非_當它後面還有未完成的語句,比如do  語句中的“while”或者if語句中的“else”,想這樣:    do {  body of do-loop  } while (condition);    和    if (x == y) {  ..  } else if (x > y) {  ...  } else {  ....  }    原因:K&R。    還有,注意到這種括號的布局方法還減少了空行(或者說是幾乎是空行)的數目,  而且沒有減小可讀性。因為你屏幕上的空行是不可回收資源(這裡想一下25行的  終端屏幕),這樣你會有更多的空行用於加注釋。    第三章:命名  C是個斯巴達式(崇尚簡潔風格的)語言,所以你的命名方法也應該如此。與  Modula-2和Pascal程序員不同,C程序員不使用  ThisVariableIsATemporaryCounter這樣可愛的名字。一個C程序員會把一個變量  叫做“tmp”,這樣的變量名更容易寫,而且理解起來也不算太難。    _但是_,盡管人人都會對大小寫混雜的名字皺眉頭,全局變量名則必須如此。管  一個全局函數叫“foo”是故意找岔。    _全局_變量(只有在_真正_需要時才使用)需要有個描述性強的名字,這點和全  局函數一樣。如果你有個函數用於對活躍用戶進行計數,你應該叫它  “count_active_users()”,而不是“cntusr()”。    把函數的類型加入到名字中(所謂的匈牙利命名法)是腦損傷的表現 - 編譯器  知道類型,能夠對它進行檢查,這種命名法只會把程序員自己搞暈。難怪微軟做  了那麼多充滿bug的程序。 哈哈^_^,有道理,不要作繭自縛    _局部_變量應該短小扼要。如果你有個隨機的整數循環變量,可能最好叫它“i”。  把它叫做“loop_counter”是效率低下的,在不會發生混淆的情況下。類型地,  “tmp”可以被用於任何類型的存儲臨時值的變量。    如果你擔心混淆你的局部變量,那麼你就會有另一個問題,所謂的函數膨脹荷爾  蒙失衡綜合症,請看下一章。    第四章:函數  函數應該短小而甜美,而且只能做一件事。他們應該只用一兩屏幕(我們都知道,  ISO/ANSI標准屏幕大小是80x24)就能裝下,只做並且做好一件事。    函數的最大長度應該與函數的復雜性和縮進層次成反比。所以,如果你有個只有  一個很長(但很簡單)的case語句的函數,對許多case做一些很少的操作,那麼  這個函數長點也沒有關系。    但是,如果你有一個復雜的函數,你擔心一個中等智力的高一學生可能無法理解,  那麼你應該更嚴格地遵守最大長度限制。使用有描述性名字的幫助函數(你可以  讓編譯器in-line這些幫助函數,如果你認為性能很重要的話,而且編譯器恐怕  會比你做的要好)。    函數的另一個指標是局部變量的數目,局部變量的數目不應超過5-10個,否則一  定是哪裡有問題了。再設計一下這個函數,把它分解得更小一些。人的大腦一般  可以同時跟蹤7個不同的東西,超過了7個就會暈菜。雖然你很聰明,不過可能你  有時會想理解一下兩星期前所寫的代碼。    第五章:注釋  注釋是好東西,不過存在過分注釋的危險。_永遠_不要在注釋中解釋你的代碼是  如何工作的:更好的做法是寫出工作方式顯而易見的代碼,解釋糟糕的代碼是浪  費時間。    一般來說,注釋應該說明代碼在做什麼,而不是怎麼做。並且,不要把注釋加在  函數主體中:如果函數太復雜以至於必須對各個部分進行注釋,那麼你可能要再  去讀讀第四章。你可以加入一些短小的注釋來提醒或警告一些聰明(或難看)的  做法,但不要太過度。更好的選擇是,把注釋放在函數頭,說明函數在做什麼,  可能還包括它為什麼做。    第六章:你的代碼亂七八糟  沒什麼,我們都遇到過。你可能從老Unix用戶那裡聽說過“GNU emacs”會自動  對齊C源代碼,但缺省的設置不是很好(事實上,缺省設置比胡亂敲打還糟糕 -  一群使用GNU emacs猴子永遠不會做出漂亮的程序)。  靠!我就是用emacs的!不過現在自動對齊還算可以了。    所以,你或者徹底仍掉GNU emacs,或者采用更理智的設置。如果選擇後者,你  可一把下面的代碼加到你的.emacs文件中:    (defun linux-c-mode ()  "C mode with adjusted defaults for use with the Linux kernel."  (interactive)  (c-mode)  (c-set-style "K&R")  (setq c-basic-offset 8))    這會定義 M-x linux-c-mode 命令。當編寫Linux模塊時,如果你把字符串“-*-  linux-c -*-”放在文件的頭兩行中,這個模式就會被自動激活。還有,如果你  想在編輯/usr/src/linux目錄下的源文件時linux-c-mode被自動激活,你在你的.  emacs文件中需要加入    (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode)  auto-mode-alist))    但是即使你用不了emacs,並不是世界末日:你還可以使用“indent”。    又一次,GNU indent使用了和GNU emacs一樣的腦死亡設置,所以你需要給它一  些命令行選項。但是,這不算太壞,因為即使是GNU indent的作者們也意識到了  K&R的權威性(GNU的人也不是魔鬼,他們只是在這件事上被誤導了),所以你可  以使用選項“-kr -i8”(表示“K&R,8字符縮進”)運行indent。    “indent”有很多選項,特別是注釋布局部分,你可能想看看它的man手冊。但  是請記住:“indent”不能修改糟糕的程序。  個人覺得現在emacs對縮進對齊的處理已經不錯了,問題在於你使用不同的Linux  發行版,就會面對不同的.emacs文件,有時候我不得不隨身攜帶我的.emacs文件,  或者把它放在我的email的存儲箱裡面    第七章:配置文件  配置選項 (arch/xxx/config.in,以及所有Config.in文件)使用了有些不同的  縮進方式。    代碼中使用的是3字符縮進,config-選項中應該使用2字符縮進標識依賴關系。  後者只應用於bool/tristat選項。對於其他選項,采用你認為最合適的縮進方式  就可以了。例如:    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then  tristate 'Apply nitroglycerine inside the keyboard (DANGEROUS)' CONFIG_BOOM  if [ "$CONFIG_BOOM" != "n" ]; then  bool ' Output nice messages when you explode' CONFIG_CHEER  fi  fi    一般來說,所有不穩定的選項應該標為CONFIG_EXPERIMENTAL。所有可能損壞數  據的的選項應該標為(DANGEROUS),其他的試驗選項應該標為(EXPERIMENTAL)。    第八章:數據結構  供多線程使用的數據結構應該采用引用計數(reference counts)。在內核中,  垃圾回收(garbage collection)是不存在的(內核之外的垃圾回收效率不高),  這意味著你_必須_使用引用計數。    引用計數的使用能避免鎖的使用,使不同的用戶能夠並行使用數據結構 - 不需  要擔心結構會因為睡眠而突然消失。    注意到加鎖_不是




Copyright © Linux教程網 All Rights Reserved