編譯—連結—載入工具鏈

載入器(loader)

/ LOH-der /

編譯與連結產生的是磁碟上的一個檔案,但躺在磁碟上的檔案還不是執行中的程式。必須有某個東西把它複製進電腦的記憶體、佈置好它期望的環境、並把控制權交給它,好讓處理器開始執行它的指令。那個東西就是載入器,作業系統的一部分,在你一輸入 ./app 或雙擊圖示的那一刻便啟動。它是死檔案與活行程之間的橋梁。

當你啟動一個程式時,載入器讀取可執行檔的格式,從中得知哪些部分該放到哪裡,並為新行程建立一個全新的定址空間。它把程式碼區段映射進記憶體,設為唯讀且可執行;把已初始化的資料映射進可寫記憶體;為 .bss 變數保留清零的空間;佈置堆疊、程式的引數與環境變數,然後跳到程式的進入點開始執行。在現代系統上,這多半透過虛擬記憶體惰性完成:檔案的分頁只在真正被觸及時才被拉進來,所以大型程式能快速啟動而不需預先複製全部。

載入器也是一整類晚期、僅在執行期才發生的失敗所在之處,有別於編譯與連結錯誤。如果你的程式依賴某個載入器在啟動時找不到的共享函式庫,你會得到像「cannot open shared object file」這樣的錯誤,即使程式編譯與連結都完美無瑕。對於使用動態函式庫的程式,一個叫動態連結器或執行期載入器的輔助程式會在啟動時做額外的工作,找到並映射進那些共享函式庫,並在抵達 main 之前修補最後幾個位址。

$ ./app # 載入器:讀取 app 的 ELF 標頭 -> 把 .text、.data、.bss 映射進一個新的 # 定址空間 -> 佈置堆疊、argv、envp -> 跳到進入點 # (接著 C 啟動程式碼執行,最後才呼叫 main)

啟動程式會執行載入器,它把靜態檔案變成記憶體中的活行程。

「它編譯且連結成功了」不代表它能載入:缺少共享函式庫會在啟動時產生執行期載入器錯誤,遠在建構成功之後。

又稱
program loader載入器