0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何修改Linux內(nèi)核代碼風(fēng)格?

Linux閱碼場(chǎng) ? 來(lái)源:CSDN博客 ? 作者: Mr qqtang ? 2021-05-13 11:27 ? 次閱讀

從編碼風(fēng)格錯(cuò)誤開(kāi)始

快速修改編碼風(fēng)格的工具

scripts/checkpatch.pl

scripts/Lindent

astyle

Linux 內(nèi)核代碼風(fēng)格

1 縮進(jìn)

2 把長(zhǎng)的行和字符串打散

3 大括號(hào)和空格的放置

4 命名

5 Typedef

6 函數(shù)

7 集中的函數(shù)退出途徑

8 注釋

9 你已經(jīng)把事情弄糟了

10 Kconfig 配置文件

11 數(shù)據(jù)結(jié)構(gòu)

12 宏,枚舉和RTL

13 打印內(nèi)核消息

14 分配內(nèi)存

15 內(nèi)聯(lián)弊病

16 函數(shù)返回值及命名

17 不要重新發(fā)明內(nèi)核宏

18 編輯器模式行和其他需要羅嗦的事情

19 內(nèi)聯(lián)匯編

20 條件編譯

從編碼風(fēng)格錯(cuò)誤開(kāi)始

曾經(jīng)在開(kāi)發(fā)Linux內(nèi)核驅(qū)動(dòng)的時(shí)候,創(chuàng)建了一個(gè)補(bǔ)丁文件,但是在把補(bǔ)丁打到主分支的時(shí)候提示很多編碼風(fēng)格的錯(cuò)誤問(wèn)題,后來(lái)重做了補(bǔ)丁才解決了問(wèn)題,這也是沒(méi)有嚴(yán)格按照的Linux編碼風(fēng)格從而導(dǎo)致的問(wèn)題。因?yàn)楫?dāng)時(shí)代碼量不大,所以解決問(wèn)題的時(shí)間相對(duì)較少。在代碼量增大的情況下可以借助工具進(jìn)行自動(dòng)修改。

快速修改編碼風(fēng)格的工具

scripts/checkpatch.pl

這是一個(gè)檢查patch是否符合內(nèi)核編碼規(guī)范的腳本。默認(rèn)的調(diào)用也確實(shí)如此。如果用來(lái)檢查原文件,需要加上-f的選項(xiàng)。

scripts/Lindent

源碼路徑下的scripts目錄中的工具Lindent可以用來(lái)自動(dòng)修改縮進(jìn)問(wèn)題。不過(guò)使用Lindent要求系統(tǒng)安裝indent這個(gè)工具。Ubuntu系統(tǒng)下可以使用apt-get install indent進(jìn)行「安裝」。

astyle

比較推薦使用這個(gè)工具,因?yàn)楸容^相當(dāng)方便,可以一鍵式轉(zhuǎn)換成linux,java,gnu等等風(fēng)格。

下載地址項(xiàng)目地址文檔說(shuō)明

如何使用,可以參考具體文檔說(shuō)明,寫(xiě)的比較詳細(xì)。

總而言之,應(yīng)該顧全大局,在進(jìn)行內(nèi)核開(kāi)發(fā)和驅(qū)動(dòng)開(kāi)發(fā)的時(shí)候,嚴(yán)格遵守Linux的編碼規(guī)范,避免由于編碼不規(guī)范帶來(lái)的種種問(wèn)題,可以參考內(nèi)核路徑下Documentation/CodingStyle文檔,以下轉(zhuǎn)自Linux內(nèi)核文檔,最權(quán)威的文檔路徑,很全很強(qiáng)大,原來(lái)在這個(gè)網(wǎng)站上已經(jīng)有中文版了,感謝萬(wàn)分,具體的更新可以跳轉(zhuǎn)到你懂的網(wǎng)址。

「來(lái)自 Documentation/process/coding-style.rst 的中文翻譯」

Linux 內(nèi)核代碼風(fēng)格

這是一個(gè)簡(jiǎn)短的文檔,描述了 linux 內(nèi)核的首選代碼風(fēng)格。代碼風(fēng)格是因人而異的, 而且我不愿意把自己的觀點(diǎn)強(qiáng)加給任何人,但這就像我去做任何事情都必須遵循的原則 那樣,我也希望在絕大多數(shù)事上保持這種的態(tài)度。請(qǐng) (在寫(xiě)代碼時(shí)) 至少考慮一下這里 的代碼風(fēng)格。

首先,我建議你打印一份 GNU 代碼規(guī)范,然后不要讀。燒了它,這是一個(gè)具有重大象征性意義的動(dòng)作。

不管怎樣,現(xiàn)在我們開(kāi)始:

1 縮進(jìn)

制表符是 8 個(gè)字符,所以縮進(jìn)也是 8 個(gè)字符。有些異端運(yùn)動(dòng)試圖將縮進(jìn)變?yōu)?4 (甚至 2?。?字符深,這幾乎相當(dāng)于嘗試將圓周率的值定義為 3。

理由:縮進(jìn)的全部意義就在于清楚的定義一個(gè)控制塊起止于何處。尤其是當(dāng)你盯著你的 屏幕連續(xù)看了 20 小時(shí)之后,你將會(huì)發(fā)現(xiàn)大一點(diǎn)的縮進(jìn)會(huì)使你更容易分辨縮進(jìn)。

現(xiàn)在,有些人會(huì)抱怨 8 個(gè)字符的縮進(jìn)會(huì)使代碼向右邊移動(dòng)的太遠(yuǎn),在 80 個(gè)字符的終端 屏幕上就很難讀這樣的代碼。這個(gè)問(wèn)題的答案是,如果你需要 3 級(jí)以上的縮進(jìn),不管用 何種方式你的代碼已經(jīng)有問(wèn)題了,應(yīng)該修正你的程序。

簡(jiǎn)而言之,8 個(gè)字符的縮進(jìn)可以讓代碼更容易閱讀,還有一個(gè)好處是當(dāng)你的函數(shù)嵌套太 深的時(shí)候可以給你警告。留心這個(gè)警告。

在 switch 語(yǔ)句中消除多級(jí)縮進(jìn)的首選的方式是讓 switch 和從屬于它的 case 標(biāo)簽對(duì)齊于同一列,而不要 兩次縮進(jìn) case 標(biāo)簽。比如:

switch (suffix) {

case ‘G’:

case ‘g’:

mem 《《= 30;

break;

case ‘M’:

case ‘m’:

mem 《《= 20;

break;

case ‘K’:

case ‘k’:

mem 《《= 10;

/* fall through */

default:

break;

}

不要把多個(gè)語(yǔ)句放在一行里,除非你有什么東西要隱藏:

if (condition) do_this;

do_something_everytime;

也不要在一行里放多個(gè)賦值語(yǔ)句。內(nèi)核代碼風(fēng)格超級(jí)簡(jiǎn)單。就是避免可能導(dǎo)致別人誤讀 的表達(dá)式。

除了注釋、文檔和 Kconfig 之外,不要使用空格來(lái)縮進(jìn),前面的例子是例外,是有意為 之。

選用一個(gè)好的編輯器,不要在行尾留空格。

2 把長(zhǎng)的行和字符串打散

代碼風(fēng)格的意義就在于使用平常使用的工具來(lái)維持代碼的可讀性和可維護(hù)性。

每一行的長(zhǎng)度的限制是 80 列,我們強(qiáng)烈建議您遵守這個(gè)慣例。

長(zhǎng)于 80 列的語(yǔ)句要打散成有意義的片段。除非超過(guò) 80 列能顯著增加可讀性,并且不 會(huì)隱藏信息。子片段要明顯短于母片段,并明顯靠右。這同樣適用于有著很長(zhǎng)參數(shù)列表 的函數(shù)頭。然而,絕對(duì)不要打散對(duì)用戶可見(jiàn)的字符串,例如 printk 信息,因?yàn)檫@樣就 很難對(duì)它們 grep。

3 大括號(hào)和空格的放置

C 語(yǔ)言風(fēng)格中另外一個(gè)常見(jiàn)問(wèn)題是大括號(hào)的放置。和縮進(jìn)大小不同,選擇或棄用某種放 置策略并沒(méi)有多少技術(shù)上的原因,不過(guò)首選的方式,就像 Kernighan 和 Ritchie 展示 給我們的,是把起始大括號(hào)放在行尾,而把結(jié)束大括號(hào)放在行首,所以:

if (x is true) {

we do y

}

這適用于所有的非函數(shù)語(yǔ)句塊 (if, switch, for, while, do)。比如:

switch (action) {

case KOBJ_ADD:

return “add”;

case KOBJ_REMOVE:

return “remove”;

case KOBJ_CHANGE:

return “change”;

default:

return NULL;

}

不過(guò),有一個(gè)例外,那就是函數(shù):函數(shù)的起始大括號(hào)放置于下一行的開(kāi)頭,所以:

int function(int x)

{

body of function

}

全世界的異端可能會(huì)抱怨這個(gè)不一致性是 呃 不一致的,不過(guò)所有思維健全的人 都知道 (a) K&R 是 「正確的」 并且 (b) K&R 是正確的。此外,不管怎樣函數(shù)都是特 殊的 (C 函數(shù)是不能嵌套的)。

注意結(jié)束大括號(hào)獨(dú)自占據(jù)一行,除非它后面跟著同一個(gè)語(yǔ)句的剩余部分,也就是 do 語(yǔ) 句中的 “while” 或者 if 語(yǔ)句中的 “else”,像這樣:

do {

body of do-loop

} while (condition);

if (x == y) {

。.

} else if (x 》 y) {

} else {

}

理由:K&R。

也請(qǐng)注意這種大括號(hào)的放置方式也能使空 (或者差不多空的) 行的數(shù)量最小化,同時(shí)不 失可讀性。因此,由于你的屏幕上的新行是不可再生資源 (想想 25 行的終端屏幕),你 將會(huì)有更多的空行來(lái)放置注釋。

當(dāng)只有一個(gè)單獨(dú)的語(yǔ)句的時(shí)候,不用加不必要的大括號(hào)。

if (condition)

action();

if (condition)

do_this();

else

do_that();

這并不適用于只有一個(gè)條件分支是單語(yǔ)句的情況;這時(shí)所有分支都要使用大括號(hào):

if (condition) {

do_this();

do_that();

} else {

otherwise();

}

3.1 空格

Linux 內(nèi)核的空格使用方式 (主要) 取決于它是用于函數(shù)還是關(guān)鍵字。(大多數(shù)) 關(guān)鍵字 后要加一個(gè)空格。值得注意的例外是 sizeof, typeof, alignof 和 「attribute」,這 些關(guān)鍵字某些程度上看起來(lái)更像函數(shù) (它們?cè)?Linux 里也常常伴隨小括號(hào)而使用,盡管 在 C 里這樣的小括號(hào)不是必需的,就像 struct fileinfo info; 聲明過(guò)后的 sizeof info)。

所以在這些關(guān)鍵字之后放一個(gè)空格:

if, switch, case, for, do, while

但是不要在 sizeof, typeof, alignof 或者 「attribute」 這些關(guān)鍵字之后放空格。例如,

s = sizeof(struct file);

不要在小括號(hào)里的表達(dá)式兩側(cè)加空格。這是一個(gè) 「反例」 :

s = sizeof( struct file );

當(dāng)聲明指針類型或者返回指針類型的函數(shù)時(shí), * 的首選使用方式是使之靠近變量名 或者函數(shù)名,而不是靠近類型名。例子:

char *linux_banner;

unsigned long long memparse(char *ptr, char **retptr);

char *match_strdup(substring_t *s);

在大多數(shù)二元和三元操作符兩側(cè)使用一個(gè)空格,例如下面所有這些操作符:

= + - 《 》 * / % | & ^ 《= 》= == != ? :

但是一元操作符后不要加空格:

& * + - ~ ! sizeof typeof alignof __attribute__ defined

后綴自加和自減一元操作符前不加空格:

++ --

前綴自加和自減一元操作符后不加空格:

++ --

。 和 -》 結(jié)構(gòu)體成員操作符前后不加空格。

不要在行尾留空白。有些可以自動(dòng)縮進(jìn)的編輯器會(huì)在新行的行首加入適量的空白,然后 你就可以直接在那一行輸入代碼。不過(guò)假如你最后沒(méi)有在那一行輸入代碼,有些編輯器 就不會(huì)移除已經(jīng)加入的空白,就像你故意留下一個(gè)只有空白的行。包含行尾空白的行就 這樣產(chǎn)生了。

當(dāng) git 發(fā)現(xiàn)補(bǔ)丁包含了行尾空白的時(shí)候會(huì)警告你,并且可以應(yīng)你的要求去掉行尾空白;不過(guò)如果你是正在打一系列補(bǔ)丁,這樣做會(huì)導(dǎo)致后面的補(bǔ)丁失敗,因?yàn)槟愀淖兞搜a(bǔ)丁的 上下文。

4 命名

C 是一個(gè)簡(jiǎn)樸的語(yǔ)言,你的命名也應(yīng)該這樣。和 Modula-2 和 Pascal 程序員不同, C 程序員不使用類似 ThisVariableIsATemporaryCounter 這樣華麗的名字。C 程序員會(huì) 稱那個(gè)變量為 tmp ,這樣寫(xiě)起來(lái)會(huì)更容易,而且至少不會(huì)令其難于理解。

不過(guò),雖然混用大小寫(xiě)的名字是不提倡使用的,但是全局變量還是需要一個(gè)具描述性的 名字。稱一個(gè)全局函數(shù)為 foo 是一個(gè)難以饒恕的錯(cuò)誤。

全局變量 (只有當(dāng)你 「真正」 需要它們的時(shí)候再用它) 需要有一個(gè)具描述性的名字,就 像全局函數(shù)。如果你有一個(gè)可以計(jì)算活動(dòng)用戶數(shù)量的函數(shù),你應(yīng)該叫它c(diǎn)ount_active_users() 或者類似的名字,你不應(yīng)該叫它 cntuser() 。

在函數(shù)名中包含函數(shù)類型 (所謂的匈牙利命名法) 是腦子出了問(wèn)題——編譯器知道那些類 型而且能夠檢查那些類型,這樣做只能把程序員弄糊涂了。難怪微軟總是制造出有問(wèn)題 的程序。

本地變量名應(yīng)該簡(jiǎn)短,而且能夠表達(dá)相關(guān)的含義。如果你有一些隨機(jī)的整數(shù)型的循環(huán)計(jì) 數(shù)器,它應(yīng)該被稱為 i 。叫它 loop_counter 并無(wú)益處,如果它沒(méi)有被誤解的 可能的話。類似的, tmp 可以用來(lái)稱呼任意類型的臨時(shí)變量。

如果你怕混淆了你的本地變量名,你就遇到另一個(gè)問(wèn)題了,叫做函數(shù)增長(zhǎng)荷爾蒙失衡綜 合癥。請(qǐng)看第六章 (函數(shù))。

5 Typedef

不要使用類似 vps_t 之類的東西。

對(duì)結(jié)構(gòu)體和指針使用 typedef 是一個(gè) 「錯(cuò)誤」 。當(dāng)你在代碼里看到:

vps_t a;

這代表什么意思呢?

相反,如果是這樣

struct virtual_container *a;

你就知道 a 是什么了。

很多人認(rèn)為 typedef 能提高可讀性 。實(shí)際不是這樣的。它們只在下列情況下有用:

完全不透明的對(duì)象 (這種情況下要主動(dòng)使用 typedef 來(lái) 「隱藏」 這個(gè)對(duì)象實(shí)際上 是什么)。

例如:pte_t 等不透明對(duì)象,你只能用合適的訪問(wèn)函數(shù)來(lái)訪問(wèn)它們。

?

不透明性和 “訪問(wèn)函數(shù)” 本身是不好的。我們使用 pte_t 等類型的原因在于真 的是完全沒(méi)有任何共用的可訪問(wèn)信息。

?清楚的整數(shù)類型,如此,這層抽象就可以 「幫助」 消除到底是 int 還是 long 的混淆。

u8/u16/u32 是完全沒(méi)有問(wèn)題的 typedef,不過(guò)它們更符合類別 (d) 而不是這里。

?

要這樣做,必須事出有因。如果某個(gè)變量是 unsigned long ,那么沒(méi)有必要typedef unsigned long myflags_t;

?不過(guò)如果有一個(gè)明確的原因,比如它在某種情況下可能會(huì)是一個(gè) unsigned int 而在其他情況下可能為 unsigned long ,那么就不要猶豫,請(qǐng)務(wù)必使用 typedef。

當(dāng)你使用 sparse 按字面的創(chuàng)建一個(gè) 「新」 類型來(lái)做類型檢查的時(shí)候。

和標(biāo)準(zhǔn) C99 類型相同的類型,在某些例外的情況下。

雖然讓眼睛和腦筋來(lái)適應(yīng)新的標(biāo)準(zhǔn)類型比如 uint32_t 不需要花很多時(shí)間,可 是有些人仍然拒絕使用它們。

因此,Linux 特有的等同于標(biāo)準(zhǔn)類型的 u8/u16/u32/u64 類型和它們的有符號(hào) 類型是被允許的——盡管在你自己的新代碼中,它們不是強(qiáng)制要求要使用的。

當(dāng)編輯已經(jīng)使用了某個(gè)類型集的已有代碼時(shí),你應(yīng)該遵循那些代碼中已經(jīng)做出的選 擇。

可以在用戶空間安全使用的類型。

在某些用戶空間可見(jiàn)的結(jié)構(gòu)體里,我們不能要求 C99 類型而且不能用上面提到的 u32 類型。因此,我們?cè)谂c用戶空間共享的所有結(jié)構(gòu)體中使用 __u32 和類似 的類型。

可能還有其他的情況,不過(guò)基本的規(guī)則是 「永遠(yuǎn)不要」 使用 typedef,除非你可以明 確的應(yīng)用上述某個(gè)規(guī)則中的一個(gè)。

總的來(lái)說(shuō),如果一個(gè)指針或者一個(gè)結(jié)構(gòu)體里的元素可以合理的被直接訪問(wèn)到,那么它們 就不應(yīng)該是一個(gè) typedef。

6 函數(shù)

函數(shù)應(yīng)該簡(jiǎn)短而漂亮,并且只完成一件事情。函數(shù)應(yīng)該可以一屏或者兩屏顯示完 (我們 都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。

一個(gè)函數(shù)的最大長(zhǎng)度是和該函數(shù)的復(fù)雜度和縮進(jìn)級(jí)數(shù)成反比的。所以,如果你有一個(gè)理 論上很簡(jiǎn)單的只有一個(gè)很長(zhǎng) (但是簡(jiǎn)單) 的 case 語(yǔ)句的函數(shù),而且你需要在每個(gè) case 里做很多很小的事情,這樣的函數(shù)盡管很長(zhǎng),但也是可以的。

不過(guò),如果你有一個(gè)復(fù)雜的函數(shù),而且你懷疑一個(gè)天分不是很高的高中一年級(jí)學(xué)生可能 甚至搞不清楚這個(gè)函數(shù)的目的,你應(yīng)該嚴(yán)格遵守前面提到的長(zhǎng)度限制。使用輔助函數(shù), 并為之取個(gè)具描述性的名字 (如果你覺(jué)得它們的性能很重要的話,可以讓編譯器內(nèi)聯(lián)它 們,這樣的效果往往會(huì)比你寫(xiě)一個(gè)復(fù)雜函數(shù)的效果要好。)

函數(shù)的另外一個(gè)衡量標(biāo)準(zhǔn)是本地變量的數(shù)量。此數(shù)量不應(yīng)超過(guò) 5-10 個(gè),否則你的函數(shù) 就有問(wèn)題了。重新考慮一下你的函數(shù),把它分拆成更小的函數(shù)。人的大腦一般可以輕松 的同時(shí)跟蹤 7 個(gè)不同的事物,如果再增多的話,就會(huì)糊涂了。即便你聰穎過(guò)人,你也可 能會(huì)記不清你 2 個(gè)星期前做過(guò)的事情。

在源文件里,使用空行隔開(kāi)不同的函數(shù)。如果該函數(shù)需要被導(dǎo)出,它的 「EXPORT」 宏 應(yīng)該緊貼在它的結(jié)束大括號(hào)之下。比如:

int system_is_up(void)

{

return system_state == SYSTEM_RUNNING;

}

EXPORT_SYMBOL(system_is_up);

在函數(shù)原型中,包含函數(shù)名和它們的數(shù)據(jù)類型。雖然 C 語(yǔ)言里沒(méi)有這樣的要求,在 Linux 里這是提倡的做法,因?yàn)檫@樣可以很簡(jiǎn)單的給讀者提供更多的有價(jià)值的信息。

7 集中的函數(shù)退出途徑

雖然被某些人聲稱已經(jīng)過(guò)時(shí),但是 goto 語(yǔ)句的等價(jià)物還是經(jīng)常被編譯器所使用,具體 形式是無(wú)條件跳轉(zhuǎn)指令。

當(dāng)一個(gè)函數(shù)從多個(gè)位置退出,并且需要做一些類似清理的常見(jiàn)操作時(shí),goto 語(yǔ)句就很方 便了。如果并不需要清理操作,那么直接 return 即可。

選擇一個(gè)能夠說(shuō)明 goto 行為或它為何存在的標(biāo)簽名。如果 goto 要釋放 buffer, 一個(gè)不錯(cuò)的名字可以是 out_free_buffer: 。別去使用像 err1: 和 err2: 這樣的GW_BASIC 名稱,因?yàn)橐坏┠闾砑踊騽h除了 (函數(shù)的) 退出路徑,你就必須對(duì)它們 重新編號(hào),這樣會(huì)難以去檢驗(yàn)正確性。

使用 goto 的理由是:

無(wú)條件語(yǔ)句容易理解和跟蹤

嵌套程度減小

可以避免由于修改時(shí)忘記更新個(gè)別的退出點(diǎn)而導(dǎo)致錯(cuò)誤

讓編譯器省去刪除冗余代碼的工作 ;)

int fun(int a)

{

int result = 0;

char *buffer;

buffer = kmalloc(SIZE, GFP_KERNEL);

if (!buffer)

return -ENOMEM;

if (condition1) {

while (loop1) {

}

result = 1;

goto out_free_buffer;

}

out_free_buffer:

kfree(buffer);

return result;

}

一個(gè)需要注意的常見(jiàn)錯(cuò)誤是 一個(gè) err 錯(cuò)誤 ,就像這樣:

err:

kfree(foo-》bar);

kfree(foo);

return ret;

這段代碼的錯(cuò)誤是,在某些退出路徑上 foo 是 NULL。通常情況下,通過(guò)把它分離 成兩個(gè)錯(cuò)誤標(biāo)簽 err_free_bar: 和 err_free_foo: 來(lái)修復(fù)這個(gè)錯(cuò)誤:

err_free_bar:

kfree(foo-》bar);

err_free_foo:

kfree(foo);

return ret;

理想情況下,你應(yīng)該模擬錯(cuò)誤來(lái)測(cè)試所有退出路徑。

8 注釋

注釋是好的,不過(guò)有過(guò)度注釋的危險(xiǎn)。永遠(yuǎn)不要在注釋里解釋你的代碼是如何運(yùn)作的:更好的做法是讓別人一看你的代碼就可以明白,解釋寫(xiě)的很差的代碼是浪費(fèi)時(shí)間。

一般的,你想要你的注釋告訴別人你的代碼做了什么,而不是怎么做的。也請(qǐng)你不要把 注釋放在一個(gè)函數(shù)體內(nèi)部:如果函數(shù)復(fù)雜到你需要獨(dú)立的注釋其中的一部分,你很可能 需要回到第六章看一看。你可以做一些小注釋來(lái)注明或警告某些很聰明 (或者槽糕) 的 做法,但不要加太多。你應(yīng)該做的,是把注釋放在函數(shù)的頭部,告訴人們它做了什么, 也可以加上它做這些事情的原因。

當(dāng)注釋內(nèi)核 API 函數(shù)時(shí),請(qǐng)使用 kernel-doc 格式。請(qǐng)看 Documentation/doc-guide/ 和 scripts/kernel-doc 以獲得詳細(xì)信息。

長(zhǎng) (多行) 注釋的首選風(fēng)格是:

/*

* 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.

*/

對(duì)于在 net/ 和 drivers/net/ 的文件,首選的長(zhǎng) (多行) 注釋風(fēng)格有些不同。

/* The preferred comment style for files in net/ and drivers/net

* looks like this.

*

* It is nearly the same as the generally preferred comment style,

* but there is no initial almost-blank line.

*/

注釋數(shù)據(jù)也是很重要的,不管是基本類型還是衍生類型。為了方便實(shí)現(xiàn)這一點(diǎn),每一行 應(yīng)只聲明一個(gè)數(shù)據(jù) (不要使用逗號(hào)來(lái)一次聲明多個(gè)數(shù)據(jù))。這樣你就有空間來(lái)為每個(gè)數(shù)據(jù) 寫(xiě)一段小注釋來(lái)解釋它們的用途了。

9 你已經(jīng)把事情弄糟了

這沒(méi)什么,我們都是這樣??赡苣愕氖褂昧撕荛L(zhǎng)時(shí)間 Unix 的朋友已經(jīng)告訴你 GNU emacs 能自動(dòng)幫你格式化 C 源代碼,而且你也注意到了,確實(shí)是這樣,不過(guò)它 所使用的默認(rèn)值和我們想要的相去甚遠(yuǎn) (實(shí)際上,甚至比隨機(jī)打的還要差——無(wú)數(shù)個(gè)猴子 在 GNU emacs 里打字永遠(yuǎn)不會(huì)創(chuàng)造出一個(gè)好程序) (譯注:Infinite Monkey Theorem)

所以你要么放棄 GNU emacs,要么改變它讓它使用更合理的設(shè)定。要采用后一個(gè)方案, 你可以把下面這段粘貼到你的 .emacs 文件里。

(defun c-lineup-arglist-tabs-only (ignored)

“Line up argument lists by tabs, not spaces”

(let* ((anchor (c-langelem-pos c-syntactic-element))

(column (c-langelem-2nd-pos c-syntactic-element))

(offset (- (1+ column) anchor))

(steps (floor offset c-basic-offset)))

(* (max steps 1)

c-basic-offset)))

(add-hook ‘c-mode-common-hook

(lambda ()

;; Add kernel style

(c-add-style

“l(fā)inux-tabs-only”

’(“l(fā)inux” (c-offsets-alist

(arglist-cont-nonempty

c-lineup-gcc-asm-reg

c-lineup-arglist-tabs-only))))))

(add-hook ‘c-mode-hook

(lambda ()

(let ((filename (buffer-file-name)))

;; Enable kernel mode for the appropriate files

(when (and filename

(string-match (expand-file-name “~/src/linux-trees”)

filename))

(setq indent-tabs-mode t)

(setq show-trailing-whitespace t)

(c-set-style “l(fā)inux-tabs-only”)))))

這會(huì)讓 emacs 在 ~/src/linux-trees 下的 C 源文件獲得更好的內(nèi)核代碼風(fēng)格。

不過(guò)就算你嘗試讓 emacs 正確的格式化代碼失敗了,也并不意味著你失去了一切:還可 以用 indent 。

不過(guò),GNU indent 也有和 GNU emacs 一樣有問(wèn)題的設(shè)定,所以你需要給它一些命令選 項(xiàng)。不過(guò),這還不算太糟糕,因?yàn)榫退闶?GNU indent 的作者也認(rèn)同 K&R 的權(quán)威性 (GNU 的人并不是壞人,他們只是在這個(gè)問(wèn)題上被嚴(yán)重的誤導(dǎo)了),所以你只要給 indent 指定選項(xiàng) -kr -i8 (代表 K&R,8 字符縮進(jìn)),或使用 scripts/Lindent 這樣就可以以最時(shí)髦的方式縮進(jìn)源代碼。

indent 有很多選項(xiàng),特別是重新格式化注釋的時(shí)候,你可能需要看一下它的手冊(cè)。不過(guò)記住:indent 不能修正壞的編程習(xí)慣。

10 Kconfig 配置文件

對(duì)于遍布源碼樹(shù)的所有 Kconfig* 配置文件來(lái)說(shuō),它們縮進(jìn)方式有所不同。緊挨著 config 定義的行,用一個(gè)制表符縮進(jìn),然而 help 信息的縮進(jìn)則額外增加 2 個(gè)空 格。舉個(gè)例子:

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.

而那些危險(xiǎn)的功能 (比如某些文件系統(tǒng)的寫(xiě)支持) 應(yīng)該在它們的提示字符串里顯著的聲 明這一點(diǎn):

config ADFS_FS_RW

bool “ADFS write support (DANGEROUS)”

depends on ADFS_FS

要查看配置文件的完整文檔,請(qǐng)看 Documentation/kbuild/kconfig-language.txt。

11 數(shù)據(jù)結(jié)構(gòu)

如果一個(gè)數(shù)據(jù)結(jié)構(gòu),在創(chuàng)建和銷毀它的單線執(zhí)行環(huán)境之外可見(jiàn),那么它必須要有一個(gè)引 用計(jì)數(shù)器。內(nèi)核里沒(méi)有垃圾收集 (并且內(nèi)核之外的垃圾收集慢且效率低下),這意味著你 絕對(duì)需要記錄你對(duì)這種數(shù)據(jù)結(jié)構(gòu)的使用情況。

引用計(jì)數(shù)意味著你能夠避免上鎖,并且允許多個(gè)用戶并行訪問(wèn)這個(gè)數(shù)據(jù)結(jié)構(gòu)——而不需要 擔(dān)心這個(gè)數(shù)據(jù)結(jié)構(gòu)僅僅因?yàn)闀簳r(shí)不被使用就消失了,那些用戶可能不過(guò)是沉睡了一陣或 者做了一些其他事情而已。

注意上鎖 「不能」 取代引用計(jì)數(shù)。上鎖是為了保持?jǐn)?shù)據(jù)結(jié)構(gòu)的一致性,而引用計(jì)數(shù)是一 個(gè)內(nèi)存管理技巧。通常二者都需要,不要把兩個(gè)搞混了。

很多數(shù)據(jù)結(jié)構(gòu)實(shí)際上有 2 級(jí)引用計(jì)數(shù),它們通常有不同 類 的用戶。子類計(jì)數(shù)器統(tǒng) 計(jì)子類用戶的數(shù)量,每當(dāng)子類計(jì)數(shù)器減至零時(shí),全局計(jì)數(shù)器減一。

這種 多級(jí)引用計(jì)數(shù) 的例子可以在內(nèi)存管理 (struct mm_struct: mm_users 和 mm_count),和文件系統(tǒng) (struct super_block: s_count 和 s_active) 中找到。

記?。喝绻硪粋€(gè)執(zhí)行線索可以找到你的數(shù)據(jù)結(jié)構(gòu),但這個(gè)數(shù)據(jù)結(jié)構(gòu)沒(méi)有引用計(jì)數(shù)器, 這里幾乎肯定是一個(gè) bug。

12 宏,枚舉和RTL

用于定義常量的宏的名字及枚舉里的標(biāo)簽需要大寫(xiě)。

#define CONSTANT 0x12345

在定義幾個(gè)相關(guān)的常量時(shí),最好用枚舉。

宏的名字請(qǐng)用大寫(xiě)字母,不過(guò)形如函數(shù)的宏的名字可以用小寫(xiě)字母。

一般的,如果能寫(xiě)成內(nèi)聯(lián)函數(shù)就不要寫(xiě)成像函數(shù)的宏。

含有多個(gè)語(yǔ)句的宏應(yīng)該被包含在一個(gè) do-while 代碼塊里:

#define macrofun(a, b, c)

do {

if (a == 5)

do_this(b, c);

} while (0)

使用宏的時(shí)候應(yīng)避免的事情:

影響控制流程的宏:

#define FOO(x)

do {

if (blah(x) 《 0)

return -EBUGGERED;

} while (0)

「非常」 不好。它看起來(lái)像一個(gè)函數(shù),不過(guò)卻能導(dǎo)致 調(diào)用 它的函數(shù)退出;不要打 亂讀者大腦里的語(yǔ)法分析器。

依賴于一個(gè)固定名字的本地變量的宏:

#define FOO(val) bar(index, val)

可能看起來(lái)像是個(gè)不錯(cuò)的東西,不過(guò)它非常容易把讀代碼的人搞糊涂,而且容易導(dǎo)致看起 來(lái)不相關(guān)的改動(dòng)帶來(lái)錯(cuò)誤。

作為左值的帶參數(shù)的宏:FOO(x) = y;如果有人把 FOO 變成一個(gè)內(nèi)聯(lián)函數(shù)的話,這 種用法就會(huì)出錯(cuò)了。

忘記了優(yōu)先級(jí):使用表達(dá)式定義常量的宏必須將表達(dá)式置于一對(duì)小括號(hào)之內(nèi)。帶參數(shù) 的宏也要注意此類問(wèn)題。

#define CONSTANT 0x4000

#define CONSTEXP (CONSTANT | 3)

在宏里定義類似函數(shù)的本地變量時(shí)命名沖突:

#define FOO(x)

({

typeof(x) ret;

ret = calc_ret(x);

(ret);

})

ret 是本地變量的通用名字 - __foo_ret 更不容易與一個(gè)已存在的變量沖突。

cpp 手冊(cè)對(duì)宏的講解很詳細(xì)。gcc internals 手冊(cè)也詳細(xì)講解了 RTL,內(nèi)核里的匯編語(yǔ) 言經(jīng)常用到它。

13 打印內(nèi)核消息

內(nèi)核開(kāi)發(fā)者應(yīng)該是受過(guò)良好教育的。請(qǐng)一定注意內(nèi)核信息的拼寫(xiě),以給人以好的印象。不要用不規(guī)范的單詞比如 dont,而要用 do not 或者 don’t 。保證這些信 息簡(jiǎn)單明了,無(wú)歧義。

內(nèi)核信息不必以英文句號(hào)結(jié)束。

在小括號(hào)里打印數(shù)字 (%d) 沒(méi)有任何價(jià)值,應(yīng)該避免這樣做。

《linux/device.h》 里有一些驅(qū)動(dòng)模型診斷宏,你應(yīng)該使用它們,以確保信息對(duì)應(yīng)于正確 的設(shè)備和驅(qū)動(dòng),并且被標(biāo)記了正確的消息級(jí)別。這些宏有:dev_err(), dev_warn(), dev_info() 等等。對(duì)于那些不和某個(gè)特定設(shè)備相關(guān)連的信息,《linux/printk.h》 定義了 pr_notice(), pr_info(), pr_warn(), pr_err()和其他。

寫(xiě)出好的調(diào)試信息可以是一個(gè)很大的挑戰(zhàn);一旦你寫(xiě)出后,這些信息在遠(yuǎn)程除錯(cuò)時(shí)能提 供極大的幫助。然而打印調(diào)試信息的處理方式同打印非調(diào)試信息不同。其他 pr_XXX() 函數(shù)能無(wú)條件地打印,pr_debug() 卻不;默認(rèn)情況下它不會(huì)被編譯,除非定義了 DEBUG 或設(shè)定了 CONFIG_DYNAMIC_DEBUG。實(shí)際這同樣是為了 dev_dbg(),一個(gè)相關(guān)約定是在一 個(gè)已經(jīng)開(kāi)啟了 DEBUG 時(shí),使用 VERBOSE_DEBUG 來(lái)添加 dev_vdbg()。

許多子系統(tǒng)擁有 Kconfig 調(diào)試選項(xiàng)來(lái)開(kāi)啟 -DDEBUG 在對(duì)應(yīng)的 Makefile 里面;在其他 情況下,特殊文件使用 #define DEBUG。當(dāng)一條調(diào)試信息需要被無(wú)條件打印時(shí),例如, 如果已經(jīng)包含一個(gè)調(diào)試相關(guān)的 #ifdef 條件,printk(KERN_DEBUG ) 就可被使用。

14 分配內(nèi)存

內(nèi)核提供了下面的一般用途的內(nèi)存分配函數(shù):kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。請(qǐng)參考 API 文檔以獲取有關(guān)它們的詳細(xì)信息。

傳遞結(jié)構(gòu)體大小的首選形式是這樣的:

p = kmalloc(sizeof(*p), );

另外一種傳遞方式中,sizeof 的操作數(shù)是結(jié)構(gòu)體的名字,這樣會(huì)降低可讀性,并且可能 會(huì)引入 bug。有可能指針變量類型被改變時(shí),而對(duì)應(yīng)的傳遞給內(nèi)存分配函數(shù)的 sizeof 的結(jié)果不變。

強(qiáng)制轉(zhuǎn)換一個(gè) void 指針?lè)祷刂凳嵌嘤嗟?。C 語(yǔ)言本身保證了從 void 指針到其他任何 指針類型的轉(zhuǎn)換是沒(méi)有問(wèn)題的。

分配一個(gè)數(shù)組的首選形式是這樣的:

p = kmalloc_array(n, sizeof(), );

分配一個(gè)零長(zhǎng)數(shù)組的首選形式是這樣的:

p = kcalloc(n, sizeof(), );

兩種形式檢查分配大小 n * sizeof() 的溢出,如果溢出返回 NULL。

15 內(nèi)聯(lián)弊病

有一個(gè)常見(jiàn)的誤解是 內(nèi)聯(lián) 是 gcc 提供的可以讓代碼運(yùn)行更快的一個(gè)選項(xiàng)。雖然使用內(nèi)聯(lián)函數(shù)有時(shí)候是恰當(dāng)?shù)?(比如作為一種替代宏的方式,請(qǐng)看第十二章),不過(guò)很多情 況下不是這樣?!竔nline 的過(guò)度使用會(huì)使內(nèi)核變大」,從而使整個(gè)系統(tǒng)運(yùn)行速度變慢。因?yàn)轶w積大內(nèi)核會(huì)占用更多的指令高速緩存,而且會(huì)導(dǎo)致 pagecache 的可用內(nèi)存減少。想象一下,一次 pagecache 未命中就會(huì)導(dǎo)致一次磁盤(pán)尋址,將耗時(shí) 5 毫秒。

「5 毫秒的 時(shí)間內(nèi) CPU 能執(zhí)行很多很多指令?!?/p>

一個(gè)基本的原則是如果一個(gè)函數(shù)有 3 行以上,就不要把它變成內(nèi)聯(lián)函數(shù)。這個(gè)原則的一 個(gè)例外是,如果你知道某個(gè)參數(shù)是一個(gè)編譯時(shí)常量,而且因?yàn)檫@個(gè)常量你確定編譯器在 編譯時(shí)能優(yōu)化掉你的函數(shù)的大部分代碼,那仍然可以給它加上 inline 關(guān)鍵字。kmalloc() 內(nèi)聯(lián)函數(shù)就是一個(gè)很好的例子。

人們經(jīng)常主張給 static 的而且只用了一次的函數(shù)加上 inline,如此不會(huì)有任何損失, 因?yàn)闆](méi)有什么好權(quán)衡的。雖然從技術(shù)上說(shuō)這是正確的,但是實(shí)際上這種情況下即使不加 inline gcc 也可以自動(dòng)使其內(nèi)聯(lián)。而且其他用戶可能會(huì)要求移除 inline,由此而來(lái)的 爭(zhēng)論會(huì)抵消 inline 自身的潛在價(jià)值,得不償失。

16 函數(shù)返回值及命名

函數(shù)可以返回多種不同類型的值,最常見(jiàn)的一種是表明函數(shù)執(zhí)行成功或者失敗的值。這樣 的一個(gè)值可以表示為一個(gè)錯(cuò)誤代碼整數(shù) (-Exxx=失敗,0=成功) 或者一個(gè) 成功 布爾值 (0=失敗,非0=成功)。

混合使用這兩種表達(dá)方式是難于發(fā)現(xiàn)的 bug 的來(lái)源。如果 C 語(yǔ)言本身嚴(yán)格區(qū)分整形和 布爾型變量,那么編譯器就能夠幫我們發(fā)現(xiàn)這些錯(cuò)誤 不過(guò) C 語(yǔ)言不區(qū)分。為了避免 產(chǎn)生這種 bug,請(qǐng)遵循下面的慣例:

如果函數(shù)的名字是一個(gè)動(dòng)作或者強(qiáng)制性的命令,那么這個(gè)函數(shù)應(yīng)該返回錯(cuò)誤代

碼整數(shù)。如果是一個(gè)判斷,那么函數(shù)應(yīng)該返回一個(gè) “成功” 布爾值。

比如, add work 是一個(gè)命令,所以 add_work() 在成功時(shí)返回 0,在失敗時(shí)返回 -EBUSY。類似的,因?yàn)?PCI device present 是一個(gè)判斷,所以 pci_dev_present() 在成功找到一個(gè)匹配的設(shè)備時(shí)應(yīng)該返回 1,如果找不到時(shí)應(yīng)該返回 0。

所有 EXPORTed 函數(shù)都必須遵守這個(gè)慣例,所有的公共函數(shù)也都應(yīng)該如此。私有 (static) 函數(shù)不需要如此,但是我們也推薦這樣做。

返回值是實(shí)際計(jì)算結(jié)果而不是計(jì)算是否成功的標(biāo)志的函數(shù)不受此慣例的限制。一般的, 他們通過(guò)返回一些正常值范圍之外的結(jié)果來(lái)表示出錯(cuò)。典型的例子是返回指針的函數(shù), 他們使用 NULL 或者 ERR_PTR 機(jī)制來(lái)報(bào)告錯(cuò)誤。

17 不要重新發(fā)明內(nèi)核宏

頭文件 include/linux/kernel.h 包含了一些宏,你應(yīng)該使用它們,而不要自己寫(xiě)一些 它們的變種。比如,如果你需要計(jì)算一個(gè)數(shù)組的長(zhǎng)度,使用這個(gè)宏

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

類似的,如果你要計(jì)算某結(jié)構(gòu)體成員的大小,使用

#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)-》f))

還有可以做嚴(yán)格的類型檢查的 min() 和 max() 宏,如果你需要可以使用它們。你可以 自己看看那個(gè)頭文件里還定義了什么你可以拿來(lái)用的東西,如果有定義的話,你就不應(yīng) 在你的代碼里自己重新定義。

18 編輯器模式行和其他需要羅嗦的事情

有一些編輯器可以解釋嵌入在源文件里的由一些特殊標(biāo)記標(biāo)明的配置信息。比如,emacs 能夠解釋被標(biāo)記成這樣的行:

-*- mode: c -*-

或者這樣的:

/*

Local Variables:

compile-command: “gcc -DMAGIC_DEBUG_FLAG foo.c”

End:

*/

Vim 能夠解釋這樣的標(biāo)記:

/* vim:set sw=8 noet */

不要在源代碼中包含任何這樣的內(nèi)容。

每個(gè)人都有他自己的編輯器配置,你的源文件不 應(yīng)該覆蓋別人的配置。這包括有關(guān)縮進(jìn)和模式配置的標(biāo)記。人們可以使用他們自己定制 的模式,或者使用其他可以產(chǎn)生正確的縮進(jìn)的巧妙方法。

19 內(nèi)聯(lián)匯編

在特定架構(gòu)的代碼中,你可能需要內(nèi)聯(lián)匯編與 CPU 和平臺(tái)相關(guān)功能連接。需要這么做時(shí) 就不要猶豫。然而,當(dāng) C 可以完成工作時(shí),不要平白無(wú)故地使用內(nèi)聯(lián)匯編。在可能的情 況下,你可以并且應(yīng)該用 C 和硬件溝通。

請(qǐng)考慮去寫(xiě)捆綁通用位元 (wrap common bits) 的內(nèi)聯(lián)匯編的簡(jiǎn)單輔助函數(shù),別去重復(fù) 地寫(xiě)下只有細(xì)微差異內(nèi)聯(lián)匯編。記住內(nèi)聯(lián)匯編可以使用 C 參數(shù)。

大型,有一定復(fù)雜度的匯編函數(shù)應(yīng)該放在 .S 文件內(nèi),用相應(yīng)的 C 原型定義在 C 頭文 件中。匯編函數(shù)的 C 原型應(yīng)該使用 asmlinkage 。

你可能需要把匯編語(yǔ)句標(biāo)記為 volatile,用來(lái)阻止 GCC 在沒(méi)發(fā)現(xiàn)任何副作用后就把它 移除了。你不必總是這樣做,盡管,這不必要的舉動(dòng)會(huì)限制優(yōu)化。

在寫(xiě)一個(gè)包含多條指令的單個(gè)內(nèi)聯(lián)匯編語(yǔ)句時(shí),把每條指令用引號(hào)分割而且各占一行, 除了最后一條指令外,在每個(gè)指令結(jié)尾加上 nt,讓匯編輸出時(shí)可以正確地縮進(jìn)下一條 指令:

asm (“magic %reg1, #42

“more_magic %reg2, %reg3”

: /* outputs */ : /* inputs */ : /* clobbers */);

20 條件編譯

只要可能,就不要在 .c 文件里面使用預(yù)處理?xiàng)l件 (#if, #ifdef);這樣做讓代碼更難 閱讀并且更難去跟蹤邏輯。替代方案是,在頭文件中用預(yù)處理?xiàng)l件提供給那些 .c 文件 使用,再給 #else 提供一個(gè)空樁 (no-op stub) 版本,然后在 .c 文件內(nèi)無(wú)條件地調(diào)用 那些 (定義在頭文件內(nèi)的) 函數(shù)。這樣做,編譯器會(huì)避免為樁函數(shù) (stub) 的調(diào)用生成 任何代碼,產(chǎn)生的結(jié)果是相同的,但邏輯將更加清晰。

最好傾向于編譯整個(gè)函數(shù),而不是函數(shù)的一部分或表達(dá)式的一部分。與其放一個(gè) ifdef 在表達(dá)式內(nèi),不如分解出部分或全部表達(dá)式,放進(jìn)一個(gè)單獨(dú)的輔助函數(shù),并應(yīng)用預(yù)處理 條件到這個(gè)輔助函數(shù)內(nèi)。

如果你有一個(gè)在特定配置中,可能變成未使用的函數(shù)或變量,編譯器會(huì)警告它定義了但 未使用,把它標(biāo)記為 __maybe_unused 而不是將它包含在一個(gè)預(yù)處理?xiàng)l件中。(然而,如 果一個(gè)函數(shù)或變量總是未使用,就直接刪除它。)

在代碼中,盡可能地使用 IS_ENABLED 宏來(lái)轉(zhuǎn)化某個(gè) Kconfig 標(biāo)記為 C 的布爾 表達(dá)式,并在一般的 C 條件中使用它:

if (IS_ENABLED(CONFIG_SOMETHING)) {

}

編譯器會(huì)做常量折疊,然后就像使用 #ifdef 那樣去包含或排除代碼塊,所以這不會(huì)帶 來(lái)任何運(yùn)行時(shí)開(kāi)銷。然而,這種方法依舊允許 C 編譯器查看塊內(nèi)的代碼,并檢查它的正 確性 (語(yǔ)法,類型,符號(hào)引用,等等)。因此,如果條件不滿足,代碼塊內(nèi)的引用符號(hào)就 不存在時(shí),你還是必須去用 #ifdef。

在任何有意義的 #if 或 #ifdef 塊的末尾 (超過(guò)幾行的),在 #endif 同一行的后面寫(xiě)下 注解,注釋這個(gè)條件表達(dá)式。例如:

#ifdef CONFIG_SOMETHING

#endif /* CONFIG_SOMETHING */

原文標(biāo)題:吐血整理的萬(wàn)字Linux內(nèi)核源碼規(guī)范

文章出處:【微信公眾號(hào):Linuxer】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11123

    瀏覽量

    207918
  • 編碼
    +關(guān)注

    關(guān)注

    6

    文章

    915

    瀏覽量

    54651

原文標(biāo)題:吐血整理的萬(wàn)字Linux內(nèi)核源碼規(guī)范

文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    linux驅(qū)動(dòng)程序如何加載進(jìn)內(nèi)核

    ,需要了解Linux內(nèi)核的基本概念和API。以下是一些關(guān)鍵概念: 1.1 內(nèi)核模塊:Linux內(nèi)核模塊是一種動(dòng)態(tài)加載和卸載的
    的頭像 發(fā)表于 08-30 15:02 ?191次閱讀

    linux驅(qū)動(dòng)程序的編譯方法是什么

    的源代碼中,并隨內(nèi)核一起編譯。這種方法適用于驅(qū)動(dòng)程序已經(jīng)非常穩(wěn)定,且不打算頻繁修改的情況。具體步驟如下: 下載并安裝Linux內(nèi)核
    的頭像 發(fā)表于 08-30 14:46 ?166次閱讀

    Linux內(nèi)核測(cè)試技術(shù)

    Linux 內(nèi)核Linux操作系統(tǒng)的核心部分,負(fù)責(zé)管理硬件資源和提供系統(tǒng)調(diào)用接口。隨著 Linux 內(nèi)核的不斷發(fā)展和更新,其復(fù)雜性和
    的頭像 發(fā)表于 08-13 13:42 ?247次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>測(cè)試技術(shù)

    歡創(chuàng)播報(bào) 華為宣布鴻蒙內(nèi)核已超越Linux內(nèi)核

    自誕生以來(lái)的最大一次升級(jí)換代。HarmonyOS NEXT不依賴傳統(tǒng)的Unix內(nèi)核Linux內(nèi)核,而是依靠自主的鴻蒙內(nèi)核。這就意味著,鴻蒙操作系統(tǒng)最終將去掉
    的頭像 發(fā)表于 06-27 11:30 ?571次閱讀

    TQT507開(kāi)發(fā)板如何修改和保存內(nèi)核配置

    本文檔介紹如何在開(kāi)發(fā)時(shí)修改和保存內(nèi)核配置,適用于開(kāi)發(fā)板TQT507。 1.修改內(nèi)核配置 編譯時(shí)系統(tǒng)會(huì)先檢測(cè)當(dāng)前內(nèi)核源碼目錄下是否存在.con
    的頭像 發(fā)表于 12-28 14:13 ?339次閱讀
    TQT507開(kāi)發(fā)板如何<b class='flag-5'>修改</b>和保存<b class='flag-5'>內(nèi)核</b>配置

    如何修改內(nèi)核設(shè)備樹(shù)

    如何修改內(nèi)核設(shè)備樹(shù)
    的頭像 發(fā)表于 12-14 14:06 ?677次閱讀
    如何<b class='flag-5'>修改</b><b class='flag-5'>內(nèi)核</b>設(shè)備樹(shù)

    獲取Linux內(nèi)核源碼的方法

    關(guān)鍵功能,今天小編就給各位小伙伴介紹一下如何獲取Linux內(nèi)核源碼。獲取Linux內(nèi)核源碼的渠道Linux有一個(gè)龐大的開(kāi)源社區(qū),每個(gè)人都可以
    的頭像 發(fā)表于 12-13 09:49 ?537次閱讀
    獲取<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>源碼的方法

    T507開(kāi)發(fā)板如何修改和保存內(nèi)核配置

    本文檔介紹如何在開(kāi)發(fā)時(shí)修改和保存內(nèi)核配置,適用于開(kāi)發(fā)板TQT507。1.修改內(nèi)核配置編譯時(shí)系統(tǒng)會(huì)先檢測(cè)當(dāng)前內(nèi)核源碼目錄下是否存在.confi
    的頭像 發(fā)表于 12-08 11:26 ?470次閱讀
    T507開(kāi)發(fā)板如何<b class='flag-5'>修改</b>和保存<b class='flag-5'>內(nèi)核</b>配置

    AD5592r linux驅(qū)動(dòng)不支持linux4.1的內(nèi)核,怎么修改?

    AD5592r linux驅(qū)動(dòng)不支持linux4.1的內(nèi)核,不知道怎么修改,以適配linux4.1的內(nèi)核
    發(fā)表于 12-06 07:17

    linux修改網(wǎng)卡ip配置文件

    Linux是一種開(kāi)源的操作系統(tǒng),因此,它給用戶提供了很高的自由度,可以根據(jù)個(gè)人需要進(jìn)行各種定制和配置。其中,修改網(wǎng)絡(luò)接口配置文件是常見(jiàn)的操作,可以通過(guò)修改網(wǎng)卡ip配置文件來(lái)設(shè)置網(wǎng)絡(luò)接口的IP地址
    的頭像 發(fā)表于 11-17 10:51 ?1883次閱讀

    linux修改用戶名的命令

    Linux修改用戶名可以使用用戶管理命令usermod來(lái)執(zhí)行,下面將詳細(xì)介紹如何修改Linux系統(tǒng)中的用戶名。 用戶名修改概述: 在
    的頭像 發(fā)表于 11-17 09:42 ?2102次閱讀

    Linux內(nèi)核中使用的數(shù)據(jù)結(jié)構(gòu)

    Linux內(nèi)核代碼中廣泛使用了數(shù)據(jù)結(jié)構(gòu)和算法,其中最常用的兩個(gè)是鏈表和紅黑樹(shù)。 鏈表 Linux內(nèi)核代碼
    的頭像 發(fā)表于 11-09 14:24 ?383次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>中使用的數(shù)據(jù)結(jié)構(gòu)

    淺談Linux內(nèi)核源碼的Makefile、Kconfig和.config文件

    Linux內(nèi)核源碼文件繁多,搞不清Makefile、Kconfig、.config間的關(guān)系,不了解內(nèi)核編譯體系,編譯修改內(nèi)核有問(wèn)題無(wú)從下手,
    發(fā)表于 10-17 16:19 ?3297次閱讀
    淺談<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>源碼的Makefile、Kconfig和.config文件

    Linux中如何在stty修改串口波特率

    Linux內(nèi)核啟動(dòng)后,串口的波特率通常是115200或者9600,此時(shí)如果想要修改串口的波特率,在shell中通過(guò)stty指令就能完成,而不需要修改驅(qū)動(dòng)
    的頭像 發(fā)表于 10-04 15:28 ?1069次閱讀

    Linux內(nèi)核中如何修改printk等級(jí)

    KERN_SOH "7" /* 調(diào)試輸出 */ Linux內(nèi)核為printk定義了8個(gè)輸出等級(jí), KERN_EMERG
    的頭像 發(fā)表于 09-27 15:56 ?1549次閱讀