Re: [問題] 連結&載入器,分段分頁,Binding關係

作者: cole945 (躂躂..)   2015-07-11 23:13:31
※ 引述《mshockwave (夏克維夫)》之銘言:
: ※ 引述《gigigigi (gigigigi)》之銘言:
: : 何謂Binding
: : Def: 決定程式執行的起始位址。
: : 即:程式要在內存的哪個地方開始執行。
好奇問一下, 這個定義是哪來的?
就如 mshockwave 所說, 一般講 binding 是指 name binding.
而 binding time 就是指什麼時候決定 "name" 與他 "所指之事"
算是較 high-level 的事情, 偏軟體的問題, 雖然是跟位址有關,
但其實位址本身不是重點, 和 OS 也比較沒有直接關係,
這裡的定義不太正確, 所以後面的討論好像整個歪掉 orz
: : 可能的Binding時期有三個:
: : 1. Compiling Time
: : 2. Loading Time
: : 3. Execution Time
: : 3-1 : Dynamic Binding
: : 3-2 : Dynamic Loading
: : 鏈接器( Linker )是把不同部分的代碼和數據,收集、組合成為一個可加載、可執行的文
: : 件。
: : 加載器( Loader )把可執行文件從外存裝入內存並進行執行
補充一下, 平常講 loader, 一般應該是指 dynamic linker,
在 load time 時 resolve symbol 與 address 的東西.
相對於 static 的 linker, 是 link-time 時 resovle symble
你這邊講的 loader 是指把 executable 從 file system 放到 memory 的東西,
並不會做 symbol resolving, 功能比較單純. 一般 loader 不是指這個.
loader (dynamic linker) 在 GNU/linux 是 ld.so 或 ld-linux.so
linker 像是 GNU binutils 裡的 ld 或 gold (gold linker)
你提到的 loader 會是想 linux kernel 的 binfmt_elf 之類的東西,
http://lxr.free-electrons.com/source/fs/binfmt_elf.c
還有像 binfmt_script 是 linux 用來 load shell script 執行的東西
: : MMU : 分段 + 分頁
: : 分段 - 邏輯位址 -> 線性位址
: : 分頁 - 線性位址 -> 實體位址
: : _________________________________________________________________________________
: : 我被上面情況給搞的有點亂 , 有下面幾點疑惑
: : 1.
: : Binging 三個時期程式位址都算是虛擬位址?
: 是的 除非你玩的是沒MMU的處理器
: : Compiling Time 位址是由編譯器計算出來?
: 不算是 其實是由連結器那邊設定的
: : Loading Time 是由 加載器 計算出位址?
: : Execution Time : 位址是 Local Address + Base Register ?
承前面所說, binding 並不是在指位址上的問題
拿這一小段 C code 來說
static int foo (int a, int b) {
return a + b;
}
int bar () {
return foo (1, 2);
}
int qux () {
return bar ();
}
當講 xxx-time 做 binding, 也就是說在 xxx-time 後, 這個 binding 就不能再改變
但是可以通過重新 xxx 改變 binding.
"通常" 越早 binding 的話, 效率越好, overhead 越低, optimization 越容易介入
* compile-time
bar call foo, 靜態就能決定是上面那個 static int foo
例如這個階段可以做 inline optimization.
但若如果 foo 的內容改了, 那就只有重新編譯一途, 不然 bar 會和 foo 不一致
* link-time,
現在程式通常會分檔編譯, 如果不在同一個檔有定義,
那可能在 link-time 從其他的 .o 或 .a 繫結
* load-time
可以想成從程式 load 到 memory, 到他真的能開始跑前的時間.
例如, 程式中有用到 libc.so (standard C library) 的東西 (printf, etc),
那就是 load-time 才會決定要 call 哪個版本.
這時才決定的東西, 可以透過重新執行來改變 binding,
例如 printf 有 bug, 可以更新 libc.so 再重新執行,
或是可以透過 LD_PRELOAD 來影響 ld.so (loader) 要使用哪個 shard object
來的定義.
另外, qux call bar, 與 bar 之間的 binding, 在現在 GNU/Linux toolchain
的情況下, 若是 position indepedent code (PIC) 的 shared object
會是 load-time, 而不是 link-time.
* execution-time, 又指 run-time
是指程式正在 run 到時才能知道決定的, 不同語言的狀況很不一樣,
例如像 C++ 的 virtual function.
load-time 和 run-time 有時況狀很像, 但還是有差異.
很多 script 類的 language 可以直接呼叫 foo function,
foo funtion 根本就不存在 (例如 typo 的 bug), 但 run 到時才會跟你
抱怨找不到 foo. 若是 load-time 做 binding, 就會在一開始執行時就
說無法 resolving foo
而一般 C/C++ 的 PIC code 通常會經過 GOT/PLT 查表來執行,
但 run-time 查 vtable 的狀況 (overhead) 類似.
但能 optimize 的策略方法不同, load-time 在程式一開始就決定了不會改變,
若用基本的 JIT 就可以避開這個 overhead. 但 run-time 的 overhead
可能就要再透過 run-time profile 和 inline-cache 等方式
: 小弟不才 可能不完全正確 但其實元PO問的事情沒那麼複雜
: 用一句話回答的話就是:把一切交給虛擬位址就對了!
: 基本上會考慮到實體位址的就只有一位:核心
: 包括編譯器連結器在內 都是用虛擬位址在思考
: 而我剛剛講的 編譯完的位址 其實是由叫做linker script的東西設定的
: 這些script是ld在編譯的鏈結時期讀取的
: (script路徑可由 ld
作者: cobrasgo (人魚線變成鮪魚線,超帥)   2015-07-16 21:59:00
搞compiler的,我要跪著看文章了…

Links booklink

Contact Us: admin [ a t ] ucptt.com