--- tags: 系統程式 --- # **系統程式ch5:Linker/Loader** ## 簡介 * 連結器:將許多目的檔連結成一個執行檔的程式。 * 載入器:將可執行檔載入到記憶體當中執行的程式。 * 目的檔:一種由程式機器碼與資料碼所組成的格式化檔案結構,組譯時若有外部標記(extern)則必須保留這些標記以待連結時進行處理。這種保留外部標記的機器碼檔,就稱為目的檔。在目的檔中,會盡可能儲存記錄代號,而非字串。 * 最簡單的目的檔:PIC (Position Independent Code) 目的碼,相對於 PC 的定址法,因此不管目的檔被載入到記憶體的哪個位址,都可以直接執行,而不需要進行任何修正。 * 執行檔:目的檔連結完成後,就會輸出可執行檔。Windows:xxx.exe Linux:xxx.out、xxx.o<<目的檔或可執行。 | windows| Linux | | -------- | -------- | | PE (Portable Executable) | ELF (Executable Linkable Format) | ## 具交互引用的C範例 StackMain.c ```c extern void push(int x); extern int pop(); int main() { int x; push(3); x= pop(); return 0; } ``` StackFunc.c ```c extern int stack[]; extern int top; void push(int x) { stack[top++] = x; } int pop() { return stack[--top]; } ``` StackType.c ```c int stack[128]; int top = 0; ```   pc相對於程式計數器定址。 * 分段.bss .text .data....通常目的檔中也會分成這些段落。 * 標記.global(全域標記, 可以供外部的程式引用)、.extern(外部標記, 引用其他程式的標記時使用)。 ## 連結器 * 將許多目的檔連結成一個檔案。輸出: 1.一個可執行檔 2.函式庫 (Library) 3.動態函式庫 (DLL) * 更新符號表與修改記錄。 * 進行區段合併的動作:內文段 (.text)、資料段 (.data) 與 BSS (.bss) 段合併。 * 組譯後(目的碼)沒定義的外部引用,進行重定位。   ### 動態連結、靜態連結 * Windows(.dll)、Linux(.so)提供動態連結器。 * 靜態連結:連結器必須將所有使用到的函式庫連結到執行檔中。 * 動態連結:函式庫可以先不需要被連結進來,而是在執行到某函數時,才透過動態連結器尋找並連 結函式庫可以不用載入全部的函式庫, 以節省記憶體。 * 特性:通常是與位置無關的程式碼 :PIC(Position Independent Code)。 * **優點** 1.節省記憶體 2.節省連結時間 3.可以抽換函式庫 * **缺點** 1.可能造成『動態連結地獄』(DLL hell) 的困境 2.假如新的函式庫有錯, 或者與舊的程式不相容, 那麼, 原本執行正常的程式會突然出現錯誤, 甚至無法使用。 ## 載入器  * 若不是使用PIC定址,載入器需要幫忙修改。 * 載入器步驟 1.將各分段載入到記憶體。 2.利用修正記錄修改記憶體內容。 3.設定程式計數器,開始執行。 ### 動態載入 * 動態載入技術, 允許程式在執行時期, 再決定要載入哪個函式庫的技術。 ## GUN  * 拿以上三支程式為範例:先編譯後連結 -c 單獨目的檔。  最後連結的__TEXT比較大是因為call __alloca分配stack、heap大小。  ### 靜態函式庫 
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up