這是一篇簡(jiǎn)短的文章,描述了描述了linux
內(nèi)核的首選代碼風(fēng)格。目的是為了分享,作為一名linux
內(nèi)核或者驅(qū)動(dòng)開(kāi)發(fā)工程師,很有必要了解這些內(nèi)核開(kāi)發(fā)規(guī)范。
- 這些約定或者規(guī)范對(duì)我們閱讀
linux
內(nèi)核源碼、了解設(shè)計(jì)思路有很大幫助。
- 我們基于
linux
內(nèi)核做開(kāi)發(fā),也要往內(nèi)核里添加代碼,遵守開(kāi)發(fā)規(guī)范,有助于別人閱讀和理解我們的代碼。
linux
內(nèi)核代碼規(guī)范約定如下:
1.強(qiáng)烈推薦單行的寬度為八十列。
任何一行超過(guò)八十列寬度的語(yǔ)句都應(yīng)該拆分成多個(gè)行,除非超過(guò)八十列的部分可以提高可讀性且不會(huì)隱藏信息。但是,千萬(wàn)不要把用戶可見(jiàn)的字符串,比如 printk
的信息,拆分成多行,因?yàn)檫@樣會(huì)導(dǎo)致使用 grep
的時(shí)候找不到這些信息。
2.關(guān)于大括號(hào)
c語(yǔ)言里的if
,do
, while
, for
語(yǔ)句都會(huì)使用到大括號(hào),內(nèi)核代碼傾向于把左括號(hào)放在行末,把右括號(hào)放在行首,并且大括號(hào)和前面的語(yǔ)句,以及if
和后面的語(yǔ)句,都保留一個(gè)空格,例如:
以上紅圈標(biāo)注都代表一個(gè)空格。
3.關(guān)于空格
這個(gè)還是單獨(dú)列出來(lái)說(shuō)明一下吧,因?yàn)閮?nèi)核代碼里用到空格的地方太多了。
Linux
內(nèi)核風(fēng)格的空格主要用在一些關(guān)鍵字上,即在關(guān)鍵字之后添一個(gè)空格。值得關(guān)注的例外是一些長(zhǎng)得像函數(shù)的關(guān)鍵字,比如:sizeof
, typeof
, alignof
, attribute
,在 Linux
中,這些關(guān)鍵字的使用都會(huì)帶上一對(duì)括號(hào),比如sizeof(int)
。
所以在下面這些關(guān)鍵字后面需要添加一個(gè)空格:
if, switch, case, for, do, while
但是, sizeof
, typeof
, alignof
, attribute
之后則不需要添加空格:
s = sizeof(struct file);
在聲明指針或者返回值為指針的函數(shù)時(shí),星號(hào)的位置應(yīng)該緊靠著變量名或函數(shù)名,而不是類(lèi)型名,例如:
char linux_banner; unsigned long long memparse(char ptr, char *retptr); char match_strdup(substring_t *s);
在二元操作符和三元操作符周?chē)砑右粋€(gè)空格,例如:
= + - < > * / % | & ^ <= >= == != ? :
但是不要在一元操作符之后添加空格:
& * + - ~ ! sizeof typeof alignof attribute defined
4.變量命名
C
是一種簡(jiǎn)潔粗曠的語(yǔ)言,因此,你的命名也應(yīng)該是簡(jiǎn)潔的。linux
內(nèi)核里的變量定義應(yīng)該盡可能簡(jiǎn)單,在不產(chǎn)生歧義的情況下,越簡(jiǎn)單越好??梢杂孟聞澗€,但是絕對(duì)不推薦使用大寫(xiě)字母。所以,內(nèi)核里的變量和函數(shù)定義不要使用駝峰命名法。
5.函數(shù)
函數(shù)應(yīng)該短小精悍,一個(gè)函數(shù)只干一件事。幾百行代碼組成一個(gè)函數(shù)是不被推薦的。
關(guān)鍵函數(shù)的前面最好留有注釋。這樣其他人可以快速看懂你的代碼意圖:
6.注釋
多行注釋推薦格式如下:
/*
- To support ISA shared interrupts, we need to have one interrupt
- handler that ensures that the IRQ line has been deasserted
- before returning. Failing to do this will result in the IRQ
- line being stuck active, and, since ISA irqs are edge triggered,
- no more IRQs will be seen. */
7.推薦使用函數(shù)自注釋
所謂函數(shù)自注釋?zhuān)褪菑哪愕暮瘮?shù)名就可以猜到你要干什么,比如內(nèi)核的:
wait_event(), wait_event_interruptible(), wait_event_interruptible_timeout()等。
注意,寫(xiě)代碼不只是寫(xiě)給現(xiàn)在的自己,也是寫(xiě)給以后的自己,也是寫(xiě)給其他人看的。如果你回看你一年前寫(xiě)的代碼都很陌生,那說(shuō)明你的代碼規(guī)范是有問(wèn)題的。
8.常量宏和枚舉的命名都是大寫(xiě)的:
9.打印內(nèi)核或者驅(qū)動(dòng)信息
編寫(xiě)好的調(diào)試信息是一項(xiàng)巨大的挑戰(zhàn),一旦你完成了,這些信息會(huì)對(duì)遠(yuǎn)程調(diào)試產(chǎn)生巨大幫助
很多子系統(tǒng)在對(duì)應(yīng)的 makefile
里都有 Kconfig
調(diào)試選項(xiàng)來(lái)打開(kāi) -DDEBUG
,或者是在文件里定義宏 #define DEBUG
。當(dāng)調(diào)試信息可以被無(wú)條件打印,或者說(shuō)已經(jīng)編譯了和調(diào)試有關(guān)的 #ifdef
段,那么 printk
(KERN_DEBUG ...) 就可以用來(lái)打印調(diào)試信息。
10.內(nèi)聯(lián)函數(shù)(inline)
Inline
關(guān)鍵字會(huì)讓編譯器將指定的函數(shù)體插入并取代每一處調(diào)用該函數(shù)的地方(上下文),從而節(jié)省了每次調(diào)用函數(shù)帶來(lái)的額外時(shí)間開(kāi)支。然而,inline
關(guān)鍵字的泛濫,會(huì)使內(nèi)核變大,從而使整個(gè)系統(tǒng)運(yùn)行速度變慢,因?yàn)榇髢?nèi)核會(huì)占用更多的CPU高速緩存,同時(shí)會(huì)導(dǎo)致可用內(nèi)存頁(yè)緩存減少。想象一下,一次頁(yè)緩存未命中就會(huì)導(dǎo)致一次磁盤(pán)尋址,這至少耗費(fèi)5毫秒。5毫秒足夠CPU運(yùn)行很多很多的指令。
好了,以上就是我們?cè)陂喿xlinux
內(nèi)核源碼的時(shí)候的一些代碼規(guī)范的約定。linux
源碼作為世界上最規(guī)范、最嚴(yán)謹(jǐn)?shù)拇a,確實(shí)有很多值得我們學(xué)習(xí)的地方。有時(shí)候欣賞內(nèi)核代碼的時(shí)候總有一種賞心悅目的感覺(jué),這可能跟它們的良好的代碼規(guī)范有關(guān)系吧。
希望這個(gè)對(duì)大家有所幫助,然后對(duì)Linux
感興趣的同學(xué)可以看一下教程
Linux教程:http://m.hgci.cn/linux/
Linux微課:http://m.hgci.cn/minicourse/play/linuxcourse
Linux就該這么學(xué):http://m.hgci.cn/linuxprobe/