Linux內核分析第七週總結

第七章 可執行程序的裝載

可執行程序的生成

可執行程序的生成:
c語言代碼--->通過編譯器的預處理--->編譯成彙編代碼--->由彙編器編譯成目標代碼--->連接成可執行文件
shell

預處理負責把include的文件包含進來及宏替換等工做函數

以HelloWorld.c文件做爲例子:
操作系統

目標文件的格式

目標文件:命令行

  • 以".o"做爲後綴的文件
  • 可執行文件

經常使用的目標文件格式:
3d

PE文件:Windos操做系統
ELF文件:Linux操做系統(可執行,可連接)指針

以ELF文件爲例:(目標文件)blog

  • 可重定位文件(.o文件)
  • 可執行文件
  • 共享目標文件

靜態連接的ELF可執行文件與進程的地址空間

默認從0x8048000處開始加載
可執行文件加載到內存中開始執行的第一行代碼
通常靜態連接會將全部代碼放在一個代碼段
動態連接的進程會有多個代碼段進程

裝載可執行程序以前的工做

可執行程序的執行環境
內存

命令行參數:編譯器

  • shell命令行
  • main函數的參數
  • execve的參數

命令行參數和環境串都放在用戶態堆棧中

在建立一個新的用戶態堆棧的時候,其實是把命令行參數的內容和環境變量的內容經過指針的方式傳遞到系統調用的內核處理函數的,內核處理函數在建立一個新的可執行堆棧的時候會將命令行參數的內容和環境變量的內容拷貝到用戶態堆棧裏面來初始化新的可執行程序執行的上下文環境
shell程序 -> execve -> sys_execve
先函數調用參數傳遞,在系統調用參數傳遞

裝載時動態連接和運行時動態連接應用舉例

動態連接分爲可執行程序裝載時動態連接和運行時動態連接,以下代碼演示了這兩種動態連接。

  • 準備.so文件
  • 編譯成libshlibexample.so文件
  • 編譯成libdllibexample.so文件
  • 分別以共享庫和動態加載共享庫的方式使用libshlibexample.so文件和libdllibexample.so文件
  • 編譯main

可執行程序的裝載

  • 可執行程序的裝載相關關鍵問題分析
    sys_execve內部會解析可執行文件格式
    do_execve -> do_execve_common -> exec_binprm

sys_execve的內部處理過程

裝載和啓動一個可執行程序依次調用如下函數:
sys_execve() -> do_execve() -> do_execve_common() -> exec_binprm() -> search_binary_handler() -> load_elf_binary() -> start_thread()

實驗

總結:

當前進程的正文、數據、堆和棧段被exec覆蓋了,當進程調用一種exec函數時,該進程執行的程序徹底替換爲新程序,而新程序則從其main函數開始執行。 由於調用exec並不建立新進程,因此先後的進程ID並未改變。

相關文章
相關標籤/搜索