高效學(xué)習(xí)Linux內(nèi)核——從源碼中的宏下手

原創(chuàng) 作者 徐工 2020-03-19 15:10:00 Linux內(nèi)核代碼 宏定義

在閱讀Linux內(nèi)核代碼時(shí),在代碼的開(kāi)頭總是有各種各樣的宏定義,了解熟悉這些宏定義,對(duì)于代碼的理解和快速修改代碼提供了便利。有些宏相對(duì)簡(jiǎn)單,一眼便可以了解作用,有些就稍微復(fù)雜一些,需要一些邏輯,今天就給大家總結(jié)了一些常見(jiàn)的宏定義,幫助大家更快,更好的理解內(nèi)核代碼。

一、什么是宏

在C語(yǔ)言中,可以采用命令#define來(lái)定義宏。該命令允許把一個(gè)名稱指定成任何所需的文本,例如一個(gè)常量值或者一條語(yǔ)句。在定義了宏之后,無(wú)論宏名稱出現(xiàn)在源代碼的何處,預(yù)處理器都會(huì)把它用定義時(shí)指定的文本替換掉。

 

替換列表和標(biāo)識(shí)符列表都是將字符串token化以后的列表。區(qū)別在于標(biāo)識(shí)符列表使用,作為不同參數(shù)之間的分割符。每一個(gè)參數(shù)都是一個(gè)token化的列表。在宏中空白符只起到分割token的作用,空白符的多少對(duì)于預(yù)處理器是沒(méi)有意義的。

二、內(nèi)核中常見(jiàn)的宏

__CONCAT宏

"##"用于粘貼兩個(gè)參數(shù),"#"用于替換參數(shù):

 


BUILD_BUG_ON宏

 

!!(e)對(duì)e的結(jié)果進(jìn)行兩次求非。如果e為0,則結(jié)果為0;如果e不為0,則結(jié)果為1。所以上述表達(dá)式的結(jié)果有兩種:

1,condition為真時(shí),sizeof(char[-1]),產(chǎn)生錯(cuò)誤,編譯不通過(guò)

2,condition為假時(shí),sizeof(char[1]),編譯通過(guò)

例如,在飛凌6Q的3.0.35的內(nèi)核中,/driver/usb/storage/uas.c/usb接口u盤(pán)的驅(qū)動(dòng)中就有使用該宏

 


BUILD_BUG_ON_ZERO(e)宏

 

檢查表達(dá)式e是否為0,為0編譯通過(guò)且返回0;如果不為0,則編譯不通過(guò)

 

如果e為0,則該結(jié)構(gòu)體擁有一個(gè)int型的數(shù)據(jù)域,并且規(guī)定它所占的位的個(gè)數(shù)為0。

 

如果e非0,結(jié)構(gòu)體的int型數(shù)據(jù)域的位域?qū)⒆優(yōu)橐粋€(gè)負(fù)數(shù),產(chǎn)生語(yǔ)法的錯(cuò)誤


typecheck宏

該宏在/include/linux/typecheck.h中定義

 

用于檢查x是否為type類(lèi)型,如果不是會(huì)拋出(warning: comparison of distinct pointer types lacks a cast)例如,在內(nèi)核中/include/linux/rwlock.h中便使用到了該宏,用于讀寫(xiě)鎖的定義中。


 


__is_constexpr宏

 

判斷x是否為整數(shù)常量表達(dá)式:如果x是常量表達(dá)式,則(void )((long)(x) 0l)是一個(gè)空指針常量,就會(huì)使用第三個(gè)操作數(shù)即((int *)8)的類(lèi)型。如果不是常量表達(dá)式,則會(huì)使用第二個(gè)操作數(shù)void類(lèi)型。


roundup宏

該宏在/include/linux/kernel.h中被定義。

 

返回一個(gè)能夠整除y并且大于x,最接近x的值,向上取整,可用于地址的內(nèi)存對(duì)齊。


clamp宏

 

判斷val是否在lo和hi的范圍內(nèi),如果小于lo,返回lo,如果大于hi則返回hi,如果在lo和hi之間就返回val。


swap宏

 

利用typeof獲取要交換變量的類(lèi)型


container_of宏

 

根據(jù)一個(gè)結(jié)構(gòu)體變量中的成員變量來(lái)獲取整個(gè)結(jié)構(gòu)體變量的指針


ALIGN對(duì)齊宏

 

對(duì)齊是采用上對(duì)齊的方式,例如0x123以16對(duì)齊,結(jié)果是0x130,因?yàn)閷?duì)齊常在分配內(nèi)存時(shí)使用,所以分配的要比需要的大。


mdelay宏

 

忙等待函數(shù),在延遲過(guò)程中無(wú)法運(yùn)行其他任務(wù),會(huì)占用CPU時(shí)間,延遲時(shí)間是準(zhǔn)確的


三、總結(jié)

像開(kāi)頭說(shuō)的,內(nèi)核源碼中有各種各樣的宏,在這里不能一一羅列。宏的使用使得代碼開(kāi)發(fā)更加標(biāo)準(zhǔn)化,了解更多的宏,無(wú)疑可以更好的更深入的理解代碼含義,如對(duì)此有興趣,可在網(wǎng)上搜索更多的內(nèi)核宏,了解更多關(guān)于Linux內(nèi)核的知識(shí)


相關(guān)產(chǎn)品 >

  • OKT507-C 開(kāi)發(fā)板

    CPU: T507 工業(yè)級(jí)處理器,超低功耗,10年+生命周期|推薦全志工業(yè)級(jí)T507開(kāi)發(fā)板系列,飛凌OKT507-C開(kāi)發(fā)板采用全志T507 四核工業(yè)級(jí)處理器 T507設(shè)計(jì)開(kāi)發(fā),Cortex-A53架構(gòu),工業(yè)級(jí)寬溫,性能強(qiáng),低功耗,是一款高性價(jià)比的工業(yè)級(jí)產(chǎn)品,提供豐富的開(kāi)發(fā)設(shè)計(jì)資料,提供產(chǎn)品規(guī)格書(shū),軟硬件手冊(cè)等,全志的T507適用于車(chē)載電子、電力、醫(yī)療、工業(yè)控制、物聯(lián)網(wǎng)、智能終端等領(lǐng)域。

    了解詳情
    OKT507-C 開(kāi)發(fā)板
  • FETT507-C核心板

    推薦T507,全志T507核心板采用工業(yè)級(jí)處理器設(shè)計(jì)開(kāi)發(fā),提供T507規(guī)格書(shū),T507各類(lèi)設(shè)計(jì)資料。FETT507-C核心板集成全志T507四核工業(yè)級(jí)處理器設(shè)計(jì)開(kāi)發(fā),Cortex-A53架構(gòu),主頻1.5GHz,集成G31 GPU,內(nèi)存2GB DDR3L,存儲(chǔ)8GB eMMC。整板工業(yè)級(jí)運(yùn)行溫寬,支持絕大部分當(dāng)前流行的視頻及圖片格式解碼,具有穩(wěn)定可靠的工業(yè)級(jí)產(chǎn)品性能、低功耗以及豐富的用戶接口等優(yōu)勢(shì),搭載Linux、Android、Ubuntu*操作系統(tǒng),適用于車(chē)載電子、電力、醫(yī)療、工業(yè)控制、物聯(lián)網(wǎng)、智能終端等領(lǐng)域 了解詳情
    FETT507-C核心板

推薦閱讀 換一批 換一批