深入理解linux內核 —— 可執行文件執行過程(1)

可執行文件格式對應的load_binary 方法執行下列操作(我們假定這個可執行文件所在的文件系統允許文件進行內存映射並並需要一個或多個共享庫):

深入理解linux內核 —— 可執行文件執行過程(1)

1。 檢查存放在文件前128字節中的一些魔數以確認可執行格式。如果魔數不匹配,則返回錯誤碼-ENOEXEC。

2。讀可執行文件的首部。這個首部描述程序的和所需的共享庫

3。從可執行文一件獲得動態鏈接程序的路徑名,並用它來確定共享庫的位置並把它們映射到內存。

4。獲得動態鏈接程序的目錄項對象(也就獲得了索引節點對象和文件對象)。

5。檢查動態鏈接程序的執行許可權

6。把動態鏈接程序的前128字節拷貝到緩衝區

7。對動態鏈接程序類執行一些一致性檢查。

深入理解linux內核 —— 可執行文件執行過程(1)

8。調用flush_old_exec()函數釋放一個計算所佔用的幾乎所有資源。這個函數又依次執行下列操作:

  • 如果信號處理程序的表為其他進程所共享,那就分配一個新表並把舊錶引用計數器減1,而且它將進程從舊的線程組脫離。這是通過調用de_thread()函數完成的。
  • 如果與其他進程共享,就調用unshare_files() 函數拷貝一份包含進程已打開文件的files_struct結構。
  • 調用exec_mmap() 函數釋放分配給進程的內存描述符、所有線性區及所有頁表
  • 將可執行文件路徑名賦給進程描述符的comm字段。
  • 調用flush_thread()函數清除
    浮點寄存器的值和在TSS段保存的調試寄存器的值。
  • 調用flush_signal_handlers()函數,用於將每個信息恢復為默認操作,從而更新信號處理程序的表
  • 調用flush_old_files()函數關閉所有打開的文件,這些打開的文件在進程描述符的files->close_on_exec字段設置了相應的標誌。

現在,我們已經不能返回了:如果真出了差錯,這個函數再不能恢復前一個計算。

深入理解linux內核 —— 可執行文件執行過程(1)

9。清除進程描述符的PF_FORKNOEXEC標誌。這個標誌用於在進程創建時設置進程記賬,在執行一個新程序時清除進程記賬

10。設立進程新的個性,即設置進程描述符的personality字段

11。調用arch_pick_mmap_layout()。以選擇進程線性區的佈局。

12。調用setup_arg_pages() 函數為進程的用戶態堆棧分配一個新的線性區描述符,並把那個線性區插入到進程的地址空間。setup_arg_pages()還把命令行參數環境變量串所在的頁框分配給新的線性區

待續。。。。。。


分享到:


相關文章: