有關 exec system call 的前言,除了以下日記外:
也請閱讀以下日記:
Exec system call 的 service routine 'sys_execve' 主要的工作是「將外部程式(ELF image)取代掉原來的 process」,以 kernel 的角度來說,「原來的 process」就是 current。以下簡單分析 exec system call 重要關鍵,我們由 do_execve 函數看起。
do_execve 負責執行 sys_execve 的主要工作,在 do_execve 的工作流程中,我們不難發現,do_execve 最後會呼叫一個很重要的 API - search_binary_handler();在 search_binary_handler() API 裡,我們發現,此 API 會呼叫到 kernel space 的 ELF loader 來載入 ELF image 至 process memory。
Kernel 2.6 的 ELF loader 實作位於 load_elf_binary() ,此 API 實作於 fs/binfmt_elf.c 檔案。ELF loader 並非直接在前面所提到的 search_binary_handler() 裡呼叫。
ELF loader 與其它執行檔格式的 loader,是在 kernel 開機時,註冊至 kernel 裡:
static struct linux_binfmt elf_format = { .module = THIS_MODULE, .load_binary = load_elf_binary, .load_shlib = load_elf_library, .core_dump = elf_core_dump, .min_coredump = ELF_EXEC_PAGESIZE }; static int __init init_elf_binfmt(void) { return register_binfmt(&elf_format); }
當 exec system call 被叫用時,最終就會在 search_binary_handler() 裡 callback ELF loader 來載入 ELF image。
Kernel space 的 ELF loader
Kernel space 的 ELF loader 是以 segment 的觀念來讀取執行檔(ELF image),相關觀念請見以下日記:
load_elf_binary() 所做的工作有:
1. 讀取 ELF image 的 segment 資訊(由 program header table)。
2. 讀出 segment 內容。
3. 判斷是否有 program interpreter;若有,再讀取 program interpreter。
4. 將讀取到的 segment 內容取代掉 current 的內容,這個動作就是 exec system call 的重要特性。
Program interpreter 就是 dynamic loader/linker,即 /lib/ld-linux.so.2。Program interpreter 的作用是「loading shared libraries(dynamic linking)」。
我們看到 current 被外部(stored)的 ELF image 取代了,這是一個重要的里程碑,背後的意義是:ELF image 被載入到記憶體後,議題將由 ELF image 被帶入更高層次的主題 - Process Memory。
當 ELF image 成為 process memory 的形式後,就能開始研究 process memory、VMA 與 program execution(例如:scheduling)有關的議題了。
See also. |
|
Jollen's Blog 使用 Github issues 與讀者交流討論。請點擊上方的文章專屬 issue,或 open a new issue
您可透過電子郵件 jollen@jollen.org,或是 Linkedin 與我連絡。更歡迎使用微信,請搜尋 WeChat ID:jollentw