【讀書筆記】《深入理解計算機操作系統》第七章

【1】預處理編譯彙編過程

預處理器(預處理,生成ASCII碼中間文件)——》編譯器(編譯,生成ASCII碼彙編語言文件)——》彙編器(彙編,生成可重定位目標文件)——》鏈接器(鏈接,生成可執行目標文件)

 

【2】ELF格式的可重定位目標文件格式: 

 ——————

|   ELF頭          |

  ——————

|   .text          | —— 已經編譯程序的機器代碼

  ——————

|   .rodata        | —— 只讀數據

  ——————

|   .data          | —— 已經初始化的全局和靜態C變量

  ——————

|   .bss           | —— 未初始化的全局和靜態C變量

  ——————

|   .symtab        | —— 符號表,存放在程序中定義和引用的函數和全局變量信息。

  ——————

|   .rel.text      | ——

  ——————

|   .rel.data      | —— 被模塊引用或重定位的所有全局變量的重定位信息

  ——————

|   .debug         | ——

  ——————

|   .line          | ——

  ——————

|   .strtab        | —— 

  ——————

 

【3】鏈接器如何解析多重定義的全局符號

編譯時,彙編器想鏈接器輸出每個全局符號,分強弱。函數和已經初始化的全局變量是強符號,未初始化的全局變量是若符號。

連接規則1:不允許有多個同名強符號;規則2:一個強符號,多個若符號,選擇強符號;規則3:多個弱符號,任選一個(很容易引起程序運行錯誤)。

 

【4】靜態鏈接庫

靜態鏈接庫(.a)是一系列可重定位目標文件的集合,有一個頭部用來描述每個成員目標文件的大小和位置。當鏈接器運行的時候,就只會複製 .a 中需要被用到的 .o 模塊到可執行文件中。

如果庫之間不是相互獨立的,存在依賴關係,那麼命令行方式中需要左邊放依賴的庫,右邊放被依賴的庫,也就是越獨立的、越基本的庫越在右邊。

 

【5】重定位

分兩步組成:

  • 重定位節和符號定義。比如,把所有來自輸入模塊的節全部合併成一個聚合節。這一步完成之後,程序中的每條指令和全局變量都有唯一的運行時內存地址了。

  • 重定位節中的符號引用。修改代碼節和數據節中對每個符號的引用,使得它們指向正確的運行地址。

 

【6】可執行目標文件

可分爲以下三段:只讀內存段(代碼段)、讀/寫內存段(數據段)、不加載到內存的符號表和調試信息。

 

【7】加載器

當在shell中輸入 > ./a.out 的時候,shell會認爲這是一個可執行目標文件,於是便調用一段稱爲“加載器(loader)”的代碼來運行它。

 

【8】共享庫(動態鏈接庫)

  • 首先,在任何給定的文件系統中,所有引用該庫的可執行目標文件共享這個.so,而不是像靜態庫那樣把內容複製和嵌入到可執行文件中。其次,內存中,一個共享庫的.text節的一個副本可以被不同的正在運行的繼承共享。

  • 因此靜態庫更新之後,所有使用了該靜態庫的軟件需要重新連接(因爲是內嵌在可執行文件中的),而動態庫更新了之後,允許應用程序在運行時連接新的共享庫。

  • 位置無關代碼

 

【9】linux鏈接器支持打樁機制

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章