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.