標籤:
先說編譯、連結過程
1.先行編譯展開宏
2.為每一個.cxx源檔案編譯一個目標檔案
3.編譯器合成這些目標檔案成一個庫檔案,同時解析可以找到的符號引用
4.連接器把目標的庫檔案和所需要的引用的靜、動態連結程式庫進行連結,即需要把其他靜態庫合成到可執行檔中,轉換相應的符號引用為地址,然後確保所引用的其他動態連結程式庫的符號存在。最終產生可執行檔。
windows程式的啟動過程
1.作業系統首先建立相應的進程並分配私人的進程空間,然後作業系統的載入器負責把可執行檔的資料區段和程式碼片段映射到進程的虛擬記憶體空間中。
2.載入器讀入可執行程式的匯入符號表,根據這些符號表可以尋找出該可執行程式的所有依賴的動態連結程式庫。
3.載入器針對該程式的每一個動態連結程式庫調用LoadLibrary
(1)尋找對應的動態庫檔案,載入器為該動態連結程式庫確定一個合適的基地址。如果該基地址和動態連結程式庫希望記載的基地址不同,載入器還要為該庫做rebase,然後吧整個動態連結程式庫映射到進程的虛擬記憶體空間中。
(2)載入器讀取該動態連結程式庫的匯入符號表和匯出符號表,比較應用程式要求的匯入符號是否匹配該庫的匯出符號。
(3)針對該庫的匯入符號表,尋找對應的依賴的動態連結程式庫,如有跳轉,則跳到3
(4)調用該動態連結程式庫的初始化函數
4.初始化應用程式的全域變數,對於全域對象自動調用建構函式。
5.進入應用程式進入點函數開始執行
Linux
1.輸入命令,斷行符號
2.exec系統調用接管,為應用程式的運行準備一些環境便利愛那個等,並且為啟動並執行命令找到相應的解譯器。
3.通常應用程式解譯器就是ld,ld接管控制權後先需要讀取這個可執行程式的檔案的一部分,包括檔案頭及共用對象(so檔案)
4.針對每一個依賴的庫,ld需要首先讀入這個so的一部分檔案頭和相關資訊,然後遞迴尋找該共用對象所依賴的其它共用對象,直到最底層。
5.ld會把所有依賴的so映射到該程式進程空間的虛擬記憶體中(注意是 映射不是讀入),由於,每一個共用對象在該進程的虛擬記憶體空間中佔據不同的連續地區,他們的“基地址各不相同”,從而其內部的一些用絕對位址表示的符號需要做出相應的修改
6.初始化應用程式的全域變數,對於全域對象子哦的那個調用建構函式
7.從入口函數開始執行
[轉] - C++程式啟動過程