1. 程式人生 > 其它 >【GCC系列】深入理解Linux核心 -- __visible巨集定義

【GCC系列】深入理解Linux核心 -- __visible巨集定義

技術標籤:深入理解Linux核心linux核心原始碼__visiblevisibility__attribute__

__visible巨集定義

在Linux的核心原始碼裡,尤其是一些關鍵的核心函式,會包含__visible巨集,它是用來做什麼的呢?

asmlinkage __visible void __init __no_sanitize_address start_kernel(void)

那麼,它的作用是什麼?
先去找下巨集定義(估計又是和編譯器相關,而且會分不同架構去定義):

【include/linux/complier_attributes.h】
/* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-externally_005fvisible-function-attribute */
#if __has_attribute(__externally_visible__) # define __visible __attribute__((__externally_visible__)) #else # define __visible #endif 【scripts/gcc_plugins/gcc-common.h】 #ifndef __visible #define __visible __attribute__((visibility("default"))) #endif

__attribute__關鍵字定義:

__attribute 其實是個編譯器指令,告訴編譯器宣告的特性,或者讓編譯器進行更多的錯誤檢查和高階優化。

__attribute__的作用:

GNU C 的一大特色就是__attribute__ 機制。
__attribute 其實是個編譯器指令,告訴編譯器宣告的特性,或者讓編譯器進行更多的錯誤檢查和高階優化。

attribute 可以設定函式屬性(Function Attribute )、變數屬性(Variable Attribute )和型別屬性(Type Attribute )。
attribute 書寫特徵是:attribute 前後都有兩個下劃線,並切後面會緊跟一對原括弧,括弧裡面是相應的__attribute__ 引數。

attribute 語法格式為:attribute ((attribute-list))
在使用__attribute__ 引數時,你也可以在引數的前後都加上“__” (兩個下劃線),例如,使用__aligned__而不是aligned ,這樣,你就可以在相應的標頭檔案裡使用它而不用關心標頭檔案裡是否有重名的巨集定義。

__externally_visible__的含義:

externally_visible的左右的下劃線是可以去掉的,主要是為了防止重名的巨集定義。

在使用__attribute__ 引數時,你也可以在引數的前後都加上“__”(兩個下劃線),例如,使用__aligned__而不是aligned,這樣,你就可以在相應的標頭檔案裡使用它而不用關心標頭檔案裡是否有重名的巨集定義。

externally_visible的含義:
附加到全域性變數或函式的該屬性使 -整個程式命令列選項,因此該物件在當前編譯單元外部仍然可見。
如果 -整個程式 與 -flto和 gold被用作連線體外掛, externally_visible屬性被自動地新增到功能。對於其他無法生成解析檔案的連結器,externally_visible仍然需要顯式屬性。
externally_visible的作用就是使該物件在當前編譯單元外部仍然可見。

__attribute__((__externally_visible__))定義:

在C ++中,可以用visible屬性標記類的成員函式和靜態成員變數。如果知道僅應從一個共享庫中使用特定方法或靜態成員變數,這將很有用。
可以將其標記為隱藏,而該類的其餘部分具有預設可見性。必須注意避免違反“一個定義”規則;例如,將內聯方法標記為隱藏而不將整個類標記為隱藏通常是沒有用的。

這裡__attribute__((externally_visible))的定義是說明,被標記的函式或變數在當前編譯單元外部仍然可見。

在別的檔案中,可以直接呼叫該函式或變數。如果沒有使用__attribute__((externally_visible))去標記,在外部呼叫會提示找不到對應的函式(因為預設編譯時函式是被隱藏的),效果可能和核心中EXPORT_SYMBOL有點類似吧。

__attribute__((visibility("default")))定義:

預設可見性是物件檔案格式的正常情況。此值可用於可見性屬性,以覆蓋可能更改實體假定的可見性的其他選項。

在ELF上,預設可見性意味著宣告對其他模組可見,而在共享庫中,意味著宣告的實體可以被覆蓋。
在Darwin上,預設可見性意味著該宣告對其他模組可見。

預設可見性對應於該語言中的“外部連結”。

visibility ("visibility_type")定義

此屬性影響其所附宣告的連結。它可以應用於變數(請參閱“通用變數屬性”)和型別(請參見“通用型別屬性”)以及函式。 visibility 支援四個可見性型別值:預設,隱藏,受保護或內部可見性。

GCC 有個visibility屬性, 該屬性是說, 啟用這個屬性:

  1. 當-fvisibility=hidden時 動態庫中的函式預設是被隱藏的即 hidden. 除非顯示宣告為__attribute__((visibility(“default”))).
  2. 當-fvisibility=default時 動態庫中的函式預設是可見的.除非顯示宣告為__attribute__((visibility(“hidden”))).

Ps:特別說明: 這個特性是 GCC4.0 以後才有的.


參考:
https://blog.csdn.net/veryitman/article/details/46756683
gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-externally_005fvisible-function-attribute