---
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大小。

### 靜態函式庫
