高效學習Linux核心——從原始碼中的宏下手

ningmengzier發表於2020-12-14

在閱讀Linux核心程式碼時,在程式碼的開頭總是有各種各樣的宏定義,瞭解熟悉這些宏定義,對於程式碼的理解和快速修改程式碼提供了便利。 有些宏相對簡單,一眼便可以瞭解作用,有些就稍微複雜一些,需要一些邏輯。 今天就給大家總結了一些常見的宏定義,幫助大家更快,更好的理解核心程式碼。

什麼是宏

在 C 語言中,可以採用命令  #define  來定義宏。該命令允許把一個名稱指定成任何所需的文字,例如一個常量值或者一條語句。在定義了宏之後,無論宏名稱出現在原始碼的何處,前處理器都會把它用定義時指定的文字替換掉。

替換列表和識別符號列表都是將字串 token 化以後的列表。區別在於識別符號列表使用,作為不同引數之間的分割符。每一個引數都是一個 token 化的列表。在宏中空白符只起到分割 token 的作用,空白符的多少對於前處理器是沒有意義的。

核心中常見的宏

__CONCAT宏 

"##"用於貼上兩個引數,"#"用於替換引數:


 BUILD_BUG_ON宏 

!!(e) 對 e 的結果進行兩次求非。如果e為0,則結果為0;如果 e 不為0,則結果為1。所以上述表示式的結果有兩種:

1. condition為真時,sizeof(char[-1]),產生錯誤,編譯不透過;
2. condition為假時,sizeof(char[1]),編譯透過。
例如,在飛凌嵌入式i.MX6Q開發板的3.0.35的核心中,/driver/usb/storage/uas.c/usb介面u盤的驅動中就有使用該宏。

 BUILD_BU G_ON_ZERO(e) 宏

檢查表示式e是否為0,為0編譯透過且返回0;如果不為0,則編譯不透過。

如果e為0,則該結構體擁有一個int型的資料域,並且規定它所佔的位的個數為0。

如果e非0,結構體的int型資料域的位域將變為一個負數,產生語法 的錯誤。

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

用於檢查x是否為type型別,如果不是會丟擲(warning: comparison of distinct pointer types lacks a cast)例如,在核心中/include/linux/rwlock.h中便使用到了該宏,用於讀寫鎖的定義中。

__is_constexpr宏

判斷 x 是否為整數常量表示式:如果 x 是常量表示式,則 (void )((long)(x) 0l) 是一個空指標常量,就會使用第三個運算元即 ((int *)8) 的型別。如果不是常量表示式,則會使用第二個運算元 void 型別。

 roundup宏

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

返回一個能夠整除 y 並且大於 x ,最接近 x 的值,向上取整,可用於地址的記憶體對齊。

 clamp 宏


判斷 val 是否在 lo hi 的範圍內,如果小於 lo ,返回 lo ,如果大於 hi 則返回 hi ,如果在 lo hi 之間就返回 val

  swap 宏


利用 typeof 獲取要交換變數的型別。

 container_of宏 

根據一個結構體變數中的成員變數來獲取整個結構體變數的指標。

 ALIGN對齊宏 


對齊是採用上對齊的方式,例如 0x123 16 對齊,結果是 0x130 ,因為對齊常在分配記憶體時使用,所以分配的要比需要的大。

 mdelay宏 


忙等待函式,在延遲過程中無法執行其他任務,會佔用 CPU 時間,延遲時間是準確的。

總結

像開頭說的,核心原始碼中有各種各樣的宏,在這裡不能一一羅列。宏的使用使得程式碼開發更加標準化,瞭解更多的宏,無疑可以更好的更深入的理解程式碼含義,如對此有興趣,可在網上搜尋更多的核心宏,瞭解更多關於Linux核心的知識。

以上,是飛凌攻城獅給大家分享的關於Linux核心原始碼中的宏的內容,希望大家看到有所收穫,指出問題共同進步,在飛凌的技術支援和分享中獲得更多的知識。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69989353/viewspace-2741935/,如需轉載,請註明出處,否則將追究法律責任。

相關文章