我是系統編程的初學者。 我的問題與動態加載和鏈接有關。在程序中使用共享庫時,無論整個庫是加載到內存還是庫的一部分?在加載完成後或者在運行時同時發生動態鏈接。動態加載和動態鏈接
回答
究竟發生了什麼是高度平臺特定的。什麼在Linux上發生當你運行一個程序基本上是
操作系統在你的ELF二進制文件的頭讀取場找到所需各種程序程序解釋的名稱。對於32位Linux二進制文件,這通常是
/lib/ld-linux.so.2
。程序解釋程序針對您的程序啓動,並從您的二進制文件讀取動態鏈接信息。除此之外,它會搜索並加載動態鏈接庫需要
您的程序運行準備,這包括搬遷將在運行的虛擬地址的符號和解決符號,所以如果你的程序有一個電話
printf()
,將有一個未解決符號_printf
在你的二進制文件和C庫有一個導出符號同名。該符號的地址寫入二進制文件中的位置。最後,控制傳遞給你的程序。
這僅僅是一個非常粗略概述。要回答你的直接問題:加載了整個庫。詳情請見google for the linux program interpreter。
既然你標記了[linux],我假設你在談論ELF共享庫。根據您的要求,我會盡可能保持簡單。
你問,
1)運行時或唯一 我正在使用example.c特定的功能在整個sample.so被加載到內存中加載到內存 。
基本上整個共享庫被加載(實際映射)到內存中。
2)如何以及何時動態鏈接解決
動態鏈接器使用它,它已經加載,它們的地址庫的知識來執行這項工作的符號,其符號表,解決每個動態符號引用並將相應的地址寫入應用程序內存中的表中。這可以在最初加載共享對象或首次使用有關符號時執行;細節因幾個因素而異。
總的來說,我知道沒有比Ulrich Drepper的論文「How to write shared libraries」更好的參考資料。我不能良心地將它稱爲「簡單」,但它非常全面,並且大致可讀,因爲它可以給予主題的性質和範圍。
動態鏈接程序ld.so
是負責查找和加載程序所需的動態庫(也稱爲共享對象,因此.so擴展名或共享庫),準備程序運行,然後運行它。
正如其他貢獻者所解釋的,整個庫將被加載並映射到內存(使用mmap)。
所以實際上,當您嘗試在Linux下運行程序時,動態鏈接程序會在運行之前運行,並且只有在它完成其作業後,控制權纔會傳遞到可執行文件的入口點。
ld.so
實際上是一個由系統的程序加載程序運行的幫助程序,它在ELF程序頭(稱爲INTERP)中使用ELF共享庫在可執行文件中發現指令後會實際加載並執行ld.so
。
您可以檢查這個頭與
$ readelf -l ./myprogram
File type ELF is EXEC (executable file)
Entry point 0x8049e7d
There are 9 program header (...)
Program headers:
Type Décalage Adr. vir. Adr.phys. T.Fich. T.Mém. Fan Alignement
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
(...)
在這種情況下,你可以從ELF頭看到,該計劃將要求ld.so
發現在/lib/ld-linux.so.2
。
一個很好的資源,瞭解在Linux下的動態鏈接過程中發生了什麼,是讀取動態連接器的手冊頁:
http://man7.org/linux/man-pages/man8/ld.so.8.html
和實驗的動態連接器,它的環境變量用你自己的一些程序。
特別是,設置LD_DEBUG環境變量並運行一個程序,可以讓您獲得有關動態鏈接程序如何在內部工作的許多信息。
$ LD_DEBUG=all ./myprogram
你可以看到庫由程序所需要的,他們是如何緩存並在那裏,在那裏它們被映射到存儲器中,在你的可執行文件中找到的符號,其中的緩存庫版本的動態鏈接程序找到相應的符號,...
您可以將help
傳遞給環境變量以獲取可能的調試信息選項列表。
在我的系統,我得到這個:
$ LD_DEBUG=help ./myprogram
Valid options for the LD_DEBUG environment variable are:
libs display library search paths
reloc display relocation processing
files display progress for input file
symbols display symbol table processing
bindings display information about symbol binding
versions display version dependencies
scopes display scope information
all all previous options combined
statistics display relocation statistics
unused determined unused DSOs
help display this help message and exit
To direct the debugging output into a file instead of standard output
a filename can be specified using the LD_DEBUG_OUTPUT environment variable.
使用,這也可以幫助您解決在二進制文件,執行的問題在那裏,如果你的系統有一個.so文件的多個版本執行可能會失敗,並動態鏈接器恰好選擇了錯誤的鏈接器。
動態鏈接和動態加載mmap
動態共享對象(DSO)到內存中(mmaping是懶惰的 - 它只是內核不需要立即解決的文件到內存的關聯)。
通過動態加載,您可以顯式地使用dlopen
文件並使用dlsym
來查找其符號。兩者都可能會失敗。
使用動態鏈接,您只需使用符號並通過其限定名稱「鏈接」共享庫,此時鏈接器將驗證所有符號都在那裏。然後實際的鏈接在運行時發生,並且默認情況下是懶惰的。每個函數調用的行爲就好像它是
//this is called a PLT stub and it's actually assembly
static myfnptr_t real_addr;
if (real_addr)
real_addr(args...);
else
if(0==(real_addr = call_dynamic_linker(symbol_name))
print_error_and_exit_program();
動態鏈接的符號通常通過所謂的全局查找範圍進行查找。 全局查找範圍從可執行對象開始,然後按順序搜索每個鏈接的共享庫,然後依次搜索它們的依賴關係等,直到找到第一個符號爲止。
動態加載創建本地查找範圍。加載的對象通常也會動態鏈接,並且在正常查找範圍輸入之前(如果需要),它的依賴關係通常可以從全局查找範圍中解析出來。本地查找範圍可能不會用於解析全局符號,因爲動態加載允許使用dlclose()卸載。
Thankyou專家花費寶貴的時間來回答我的問題。並詳細解釋它。 – user3227126
- 1. 加載和動態鏈接
- 2. 動態鏈接v/s動態加載
- 3. 加載動態鏈接器
- 4. 鏈接動態加載javascript
- 5. 動態鏈接和動態加載有什麼區別
- 6. 動態鏈接器和動態加載器有什麼區別?
- 7. 加載時動態鏈接和運行時動態鏈接之間的區別
- 8. 動態鏈接和加載時間鏈接.DLL
- 9. jquery動態加載鏈接變化
- 10. 共享庫的動態鏈接或動態加載?
- 11. 動態鏈接
- 12. 動態鏈接
- 13. jQuery,php和Ajax問題:無法使動態鏈接加載動態內容
- 14. 動態添加鏈接到鏈接
- 15. 動態鏈接和Ajax
- 16. 動態菜單和鏈接
- 17. Angularjs和PHP動態鏈接
- 18. MFC和動態鏈接
- 19. DD4T和動態鏈接
- 20. 靜態鏈接glibc,但動態使用GCC動態鏈接glibc
- 21. 動態鏈接到靜態鏈接?
- 22. import =動態鏈接? &include =靜態鏈接?
- 23. 靜態和動態MFC鏈接
- 24. 靜態和動態庫鏈接
- 25. 靜態和動態鏈接庫
- 26. 靜態和動態鏈接沙盒
- 27. 鏈接動態和靜態庫RCPP
- 28. 什麼是靜態和動態鏈接
- 29. 動態加載DLL接口
- 30. 什麼是靜態庫,靜態鏈接動態庫和動態鏈接動態庫的.lib文件?
你想知道Linux的動態運行時加載器是如何工作的嗎?它如何加載和處理ELF文件?解析符號?處理與位置無關的代碼?這是相當廣泛的,並且可以通過下載源代碼來讀取(比如核心Linux的所有部分都是開源的)。 –
可能重複[動態加載和動態鏈接的區別?](https://stackoverflow.com/questions/10052464/difference-between-dynamic-loading-and-dynamic-linking) –