weak alias 跟 weak reference 完全沒有任何關系,不過是我在看到 weak reference 的時候想到的而已。
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 内容,
weak 和 alias 分别是兩個屬性。weak 使得 <code>foo</code> 這個符号在目标檔案中作為 weak symbol 而不是 global symbol。用
<code>nm</code> 指令檢視編譯 dummy.c 生成的目标檔案可用看到 foo 是一個 weak symbol,它前面的标記是 w。
而 alias 則使 <code>foo</code> 是 <code>__foo</code> 的一個别名,__foo 和 foo 必須在同一個編譯單元中定義,否則會編譯出錯。
那麼這個東西的用處是?看第二個檔案,func.c,
這裡有一個函數名字是 <code>foo</code>。如果我們編譯 func.c 和 dummy.c 得到兩個目标檔案,當我們同時使用 func.o 和 dummy.o 和其他目标檔案進行連結時,如果其他目标檔案裡面引用符号
<code>foo</code>,最終使用到的是 func.c 中定義的函數,而不是 <code>__foo</code>,雖然它有一個别名 <code>foo</code>。也就是說,我們最終使用到的函數會是“實際做事”的那個函數。當然,單獨使用 dummy.o 連結的話使用的是那個“不做事”的函數。如果 dummy.o 中的
<code>foo</code> 不是 weak symbol 的話,在連結時會産生沖突,這就是我們要使用 weak 的原因。
glibc 的實作裡面經常用 weak alias。比如它的 <code>socket</code> 函數,在 c 檔案裡面你會看到一個
<code>__socket</code> 函數,它幾乎什麼都沒有做,隻是設定了一些錯誤代碼,傳回些東西而已。在同一個 c 檔案裡面會再聲明一個
<code>__socket</code> 的 weak alias 别名 <code>socket</code>。實際完成工作的代碼通過彙編來實作,在另外的彙編檔案裡面會有設定系統調用号,執行
<code>sysenter</code> 或者 <code>int</code> 等動作去請求系統調用。以前看 glibc 裡面系統調用的實作的時候郁悶過很久,就是那個時候才知道了 weak alias 這個東西。