链接 动态链接 静态链接
要想了解底層,鏈接是一個不得不過的一關,我總結了下學習的心得,首先要了解鏈接器到底是如何工作的,鏈接器分為兩類,一個是靜態鏈接,一個是動態鏈接,先來講解靜態鏈接,靜態鏈接要干兩件事:
靜態鏈接的輸入文件是一系列的目標文件,輸出是可執行的目標文件。這些目標文件都可以統稱為ELF文件:executable and linkable format(可執行和可鏈接格式)。
從而引入了一個重要的知識點:ELF文件格式。
首先是可重定位目標文件的ELF文件:從上到下依次是:
| ELF頭部 |
| .text |
| .rodata |
| .data |
| .bss |
| .symtab |
| rel.text |
| rel.data |
| .debug |
| .line |
| .strtab |
| 節頭部表 |
注意上面的除了節頭部表,其余都可以叫做節,這就是一個很核心的點,節是和鏈接相關的,每一個節經過鏈接會變成段,段對應的是執行相關的,而且段對應的是可執行目標文件的ELF文件,現在就來看看經過靜態鏈接生成的可執行目標文件的ELF文件格式,這里面都是以段作為術語的:
| ELF頭部 |
| 段頭表 |
| .init |
| .text |
| .rodata |
| .data |
| .bss |
| .symtab |
| .debug |
| .line |
| .strtab |
| 節頭表 |
隨即這些段就會被加載到存儲器地址中,也就是大名鼎鼎的存儲器結構,包含棧堆,內核等等的結構。
這就是一個靜態鏈接器如何將一個可重定位文建變成可執行目標文件從而運行到平臺上。
動態鏈接有是怎么回事呢?
在了解之前,我們要知道靜態庫,剛才我們所說的都僅僅是將一系列的可重定位目標文件變成一個可執行目標文件,實際上,所有的編譯系統都提供了一種機制,將所有的目標模塊打包成一個單獨的文件,稱為靜態庫,他也可以作為靜態鏈接器的輸入,當鏈接器構造一個輸出文件時,它只需要拷貝靜態庫里被應用程序引用的目標模塊。
像一些glibc提供的函數,我們可能隨時隨處都會用上,如果我們每次把函數的代碼復制到每個進程的文本段中,這無疑是一種浪費資源,所以出來了共享庫的概念,在運行時,可以加載到任意的存儲器地址,并在存儲器中和一個程序鏈接起來,這個過程就叫做動態鏈接。共享庫也叫共享目標,以.so為結尾,像linux系統提供了dlopen這樣函數去加載和鏈接共享庫。
其實.symtab這個存放符號的地方也是值得研究的,有機會再記錄。
總結
以上是生活随笔為你收集整理的链接 动态链接 静态链接的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用堆实现第k大元素
- 下一篇: n皇后问题java版