閱讀963 返回首頁    go 阿裏雲 go 技術社區[雲棲]


weak alias

Weak Alias 跟 Weak Reference 完全沒有任何關係,不過是我在看到 Weak Reference 的時候想到的而已。

Weak Alias 是 gcc 擴展裏的東西,實際上是函數的屬性。這個東西在庫的實現裏麵可能會經常用到,比如 glibc 裏麵就用了不少。抄錄一段 gcc 手冊裏麵的話解釋下函數屬性是幹啥的,

In GNU C, you declare certain things about functions called in your program which help the compiler optimize function calls and check your code more carefully.

先上代碼,看看 weak alias 怎麼寫。第一個文件 dummy.c 內容,

#include 

/* Do some thing. */
int __foo() {
    puts(”I do no thing.”);
}

int foo() __attribute__ ((weak, alias(”__foo”)));

weak 和 alias 分別是兩個屬性。weak 使得 foo 這個符號在目標文件中作為 weak symbol 而不是 global symbol。用 nm 命令查看編譯 dummy.c 生成的目標文件可用看到 foo 是一個 weak symbol,它前麵的標記是 W。

00000000 T __foo
00000000 W foo
         U puts

而 alias 則使 foo__foo 的一個別名,__foo 和 foo 必須在同一個編譯單元中定義,否則會編譯出錯。

那麼這個東西的用處是?看第二個文件,func.c,

#include 

int foo() {
    puts(”I do something.”);
}

這裏有一個函數名字是 foo。如果我們編譯 func.c 和 dummy.c 得到兩個目標文件,當我們同時使用 func.o 和 dummy.o 和其他目標文件進行鏈接時,如果其他目標文件裏麵引用符號 foo,最終使用到的是 func.c 中定義的函數,而不是 __foo,雖然它有一個別名 foo。也就是說,我們最終使用到的函數會是“實際做事”的那個函數。當然,單獨使用 dummy.o 鏈接的話使用的是那個“不做事”的函數。如果 dummy.o 中的 foo 不是 weak symbol 的話,在鏈接時會產生衝突,這就是我們要使用 weak 的原因。

glibc 的實現裏麵經常用 weak alias。比如它的 socket 函數,在 C 文件裏麵你會看到一個 __socket 函數,它幾乎什麼都沒有做,隻是設置了一些錯誤代碼,返回些東西而已。在同一個 C 文件裏麵會再聲明一個 __socket 的 weak alias 別名 socket。實際完成工作的代碼通過匯編來實現,在另外的匯編文件裏麵會有設置係統調用號,執行 sysenter 或者 int 等動作去請求係統調用。以前看 glibc 裏麵係統調用的實現的時候鬱悶過很久,就是那個時候才知道了 weak alias 這個東西。

最後更新:2017-04-03 12:53:56

  上一篇:go GNU C 擴展之__attribute__ 機製簡介
  下一篇:go googe眼鏡開發