Static Linking
在ld時,如果找到了obj檔案中存在的reference,就會到libary中去把這個reference的binary code 添加到你的程式中去。
經過了靜態連結的程式,是一個真正完整的可啟動並執行程式,啟動並執行時候不需要其它的東東,只需要os的kernel調用這個code就行了
靜態連結中,最重要的一點:把libary中的binary 程式 添加到我們調用庫函數的程式中去了。
Dynamic Linking
動態連結時,在ld時,如果我們寫的code中調用了庫中的代碼,這裡不會把庫中的binary code直接添加我們的code中去,而是保留這個reference,在程式載入運行時,注意是在我們的code運行時,程式中保留的那個reference就會被連結程式連結到到libary中執行。動態連結的好處就是可以使on disk 程式非常的小,節約和了memory,動態連結的結果就是(shared libray),動態連結的程式是要依賴於包含reference的libary。在os中如果沒有包含這個reference的庫檔案,我們寫的程式就不能run了
Shared Libraries
共用的庫
把很多可以獨自啟動並執行檔案打包成一libary,這意味著我們不需要把libary裡的binary檔案添加到executable檔案中,在executable中的reference在運行時來調整,這樣所有execuable程式都可以到same memory中去找到libary binary。
這需要一些技巧,libary中的binary程式不能有任何的static變數,也不能有global變數,如果有static變數或是global變數,這個binary程式就要為每個調用他的程式提供一個單獨的變數空間。這種技巧通常用在多線程的程式中,一個程式可能有多個控制流程。
通過 庫檔案的位置在virtual memory中,也可能不是一定的,也就是說庫檔案的位置可能經常會變化,這就要求動態庫檔案在任何的位置都可以運行,就是產生的程式碼是與運行位置無關的。(這樣的代碼可以通過在GCC編譯時間,添加-PIC(position independent code)選項得到)。這種位置無關的代碼需要elf檔案格式的支援,位置無關的代碼的運行效率可能要低一點(這是需要付出的代價)
ABI - Application Binary Interface
應用程式與二進位程式中調用的標準:
ABI定義了 libary 中的函數是如何被調用,還有syscall是如何調用的。這個調用標準 包含了,參數儲存在stack中還是 儲存在register中,在libary中函數的進入點是放在哪裡,還有其它的一些內容。
當用static linkage時,產生的可啟動並執行程式 與kenel調用應用程式時 用的ABI標準要一樣。
當用dynamic linkage時,產生的可啟動並執行程式,與libary 中使用的ABI標準要保持一樣。
Unresolved Symbols
沒有解決的符號(就是用dynamic linkage時程式中存在的reference,或是static linkage時找不到符號)
linker會啟動並執行加入一些你不知道的reference .
如( $(V)$(LD) -o $@ $(KERN_LDFLAGS) $(KERN_OBJFILES) $(GCC_LIB) -b binary $(KERN_BINFILES) )
這些reference包含了alloca(),memset(),memcpy()還有其它的一些函數(在libgcc.a中)。
經常我們會由於沒有正常的使用tool chain或是command line配置的有問題,而無法正常的編譯出自己的os kernel。或是我們調用的一些函數在libary中沒實現。在我們ld時沒有用libgcc這個庫檔案時(包含memcpy memmove,memset,memcmp),通過會出錯。
其它的一些symbols,如做除法,_udiv,求餘_umode等。也是可以在libgcc庫檔案中找到的。如果你在ld時,missing such symbols,記住在ld時,link with libgcc.