簡體   English   中英

何時在程序和共享庫之間執行動態鏈接?

[英]When is dynamic linking between a program and a shared library performed?

在C語言中,何時在程序和共享庫之間執行動態鏈接:

  • 一旦將程序加載到內存中,但是在執行程序的main()之前,或者

  • 執行完程序的main()之后,何時執行對庫中例程的第一次調用? 當執行第二次或第三次或從庫中調用例程時,動態鏈接會再次發生嗎?

在開始閱讀以下引文之前,我一直在想第一個,現在不確定。

不確定操作系統是否重要,我使用的是Linux。

從操作系統概念:

通過動態鏈接,每個庫例程參考的映像中都包含一個存根。 存根是一小段代碼,指示如何找到合適的駐留內存的庫例程,或者如果該例程尚不存在,則如何加載該庫。

執行存根時 ,它將檢查所需的例程是否已在內存中。 如果不是,程序將例程加載到內存中。 無論哪種方式,存根都會用例程的地址替換自身並執行該例程。 因此, 下次到達特定代碼段時 ,將直接執行庫例程,而不會產生動態鏈接的開銷。 在這種方案下,所有使用語言庫的進程僅執行庫代碼的一個副本。

在開始閱讀以下引文之前,我一直在想第一個,現在不確定。

它很復雜(取決於您所謂的“動態鏈接”)。

Linux內核將a.out加載到內存中。 然后,它檢查PT_INTERP段(如果有)。

如果該段不存在,則二進制文件是靜態鏈接的,內核將控制權轉移到Elf{32,64}Ehdr.e_entry (通常是_start例程)。

如果PT_INTERP 出現,內核加載到內存中,並將控制權轉移到它的 .e_entry 動態鏈接就是在這里開始的

動態加載程序重新定位自身,然后查找在a.out小號PT_DYNAMIC段上還有什么是必要的說明。

例如,它通常會發現一個或多個DT_NEEDED項-共享庫a.out直接對鏈接。 加載器加載任何這樣的庫, 它們初始化,並解決它們之間的任何數據的引用。

如果a.outPT_DYNAMIC具有DT_FLAGS條目,並且如果該條目包含DF_BIND_NOW標志,則來自a.out 函數引用也將被解析。 否則(並假設環境中未設置LD_BIND_NOW ),將執行惰性PLT解析(將函數解析為對任何給定函數的首次調用的一部分)。 詳細信息在這里

執行存根時,它將檢查所需的例程是否已在內存中。 如果不是,程序將例程加載到內存中。

我不知道您在引用哪本書,但是當前的UNIX OS都無法使用這種方式。

操作系統(和編譯器 )當然很重要:語言本身對動態庫無話可說(一般而言,鏈接很少 )。 即使我們知道動態鏈接正在發生,嚴格遵循標准的程序也無法從其翻譯單元之間的時序觀察到任何影響(因為非本地初始化不會產生副作用 )。

也就是說,Linux上的常見工具鏈確實支持在加載動態庫時自動初始化 (用於實現C ++等)。 可執行文件和它們所依賴的動態庫(通常用-l指定)被遞歸加載和初始化,以允許每個模塊中的初始化(成功)使用其依賴關系中的函數。 (在某些情況下, 不幸的是選擇了順序。)當然, dlopen(3)可用於稍后加載和初始化更多庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM