內核裝載ELF的過程總結

面來簡單總結一些內核裝載ELF的過程總結。 簡單的說,整個流程分為三步:

1)創建一個獨立的虛擬地址空間;
2)讀取可執行文件頭,並且建立虛擬空間與可執行文件的映射關係;
3)將cpu的指令寄存器設置成可執行文件的入口地址。

過程的基本流程如下圖

首先,在用戶層,bash進程會調用fork()系統調用創建一個新的進程,然後新的進程調用exeve()系統調用執行制定的ELF文件,原先的bush進程繼續返回等待剛才啟動的新進程結束,然後繼續等待命令輸入。

exeve系統調用的原型如下:

int exeve(const char *filename, char *constt argv[], char *const envp[]);

三個參數分別是被執行的程序文件名,執行參數和環境變量。

在進入exeve()系統調用之後,Linux內核就開始進行真正的裝載工作。在內核中,execve()系統調用相應的入口是sys_execve(), sys_execve進行一些參數的檢查複製之後,調用do_execve (),doexecve()會首先查找被執行的文件,如果找到文件,則讀取文件的前128個字節,之後調用scarch_binary_handle ()去搜索和匹配何時的可執行文件裝載處理過程,對於ELF文件,相應的加載過程就是load_elf_binary().它的主要步驟是:

1)檢查ELF可執行文件格式的有效性,比如魔數等;
2)尋找動態鏈接的“.interp”端,設置動態鏈接路徑;
3)根據ELF課執行文件的程序投標的描述,對ELF文件進行映射,比如代數、數據、只讀數據;
4)初始化ELF進程環境;
5)將系統調用的返回地址修改成ELF可執行文件的入口,這個入口點取決於程序的鏈接方式,對於靜態鏈接的可執行文件,這個程序入口點就是ELF文件的文件頭中e_entry所指地址;對於動態鏈接的ELF可執行文件,程序入口點就是動態鏈接器。


當load_elf_binary()執行完畢,返回至do_execve()再返回至sys_execve()時,第五步中已經把系統調用的返回地址改成了被裝載的ELF程序的入口地址了。所以當sys_execve()系統調用從內核態返回到用戶態時,eip寄存器直接跳轉到ELF程序的入口地址,於是新的程序開始執行,ELF可執行文件裝載完成。