<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] # Windows和Linux下的文件格式 現在PC平臺上流行的可執行文件格式主要是 Windows 下的PE(Portable Executable)和 Linux 下的ELF(Executable Linkable Format),它們都是COFF(Common File Format)格式的變種。 COFF 是 Unix V3首先提出的規范,微軟在此基礎上制定了 PE 格式標準,并將它用于 Windows。后來 Unix V4 又在 COFF 的基礎上引入了 ELF 格式,被 Linux 廣泛使用。這也就是為什么 Windows 和 Linux 上的可執行文件如此相似的主要原因,因為它們都是源于同一種可執行文件格式 COFF。 從廣義上講,目標文件與可執行文件的存儲格式幾乎是一樣的,我們可以將它們看成是同一種類型的文件,在 Windows 下,將它們統稱為 PE 文件,在 Linux 下,將它們統稱為 ELF文件。 另外,動態鏈接庫(DLL,Dynamic Linking Library)(Windows 下的`.dll`和 Linux 下的`.so`)和靜態鏈接庫(Static Linking Library)(Windows 下的`.lib`和 Linux 下的`.a`)也是按照可執行文件的格式存儲的。 靜態鏈接庫稍有不同,它是把多個目標文件捆綁在一起形成一個文件,再加上一些索引,你可以簡單地把它理解為一個包含了很多目標文件的包。 其他不太常見的可執行文件格式還有 Intel/Microsoft 的 OMF(Object Module Format)、Unix a.out、MS-DOS .COM 等。 在 Linux 的 ELF 標準中,主要包含以下四類文件: ![](https://box.kancloud.cn/be882d8440ef00429c79da4ff7833953_1221x358.png) # 目標文件的組織形式 從整體上看,編譯生成的目標文件被劃分成了多個部分,每個部分叫做一個段(Section)。下圖是 Linux GCC 生成的目標文件的格式: ![](https://box.kancloud.cn/8ab29b6098bf8b367671e080374ccef5_311x493.png) 段名大都以`.`作為前綴,表示這些名字是系統保留的。下面是對各個部分的說明: ![](https://box.kancloud.cn/4f40248a47cb81b6939c712a87a43241_1219x495.png) 除了這些系統保留的段名,應用程序也可以使用其它名字定義自己的段,比如可以在 ELF 文件中插入一個叫做`music`的段來保存 MP3 音樂。應用程序自定義的的段不建議使用`.`作為前綴,否則容易和系統保留段發生沖突。 # 可執行文件的組織形式 可執行文件的組織形式和目標文件非常類似,也被劃分成多個部分,如下圖所示: ![](https://box.kancloud.cn/c19690d9b3c110ef8bdf6e04374f96c3_725x706.png) 圖中左半部分是可執行文件的結構:帶陰影的是可執行文件增加的一些段,另外可執行文件刪除了可重定位段(`.rel.text`和`.rel.data`)以及段表(Section Table)。 總體來說,目標文件包含了10個左右的段,而可執行文件包含了將近30個左右的段,上面的兩張圖只列出了一些關鍵段,剩下的段都隱藏在“Other Data(其他數據)”。 圖中右半部分是進程的地址空間 不同顏色的箭頭表明了可執行文件應該被加載到地址空間的哪一個區域,可以發現,操作系統并不是為每個段都分配一個區域,而是將多個具有相同權限的段合并在一起,加載到同一個區域。 站在文件結構的角度,可執行文件包含了眾多的段(Section),每個段都有不同的作用;站在加載和執行的角度,所有的段都是數據,操作系統只關心數據的權限,只要把相同權限的數據加載到同一個內存區域,程序就能正確執行。 常見的數據權限無外乎三種:只讀(例如 .rodata 只讀數據段)、讀寫(例如 .data 數據段)、讀取和執行(例如 .text 代碼段),我們將一塊連續的、具有相同權限的數據稱為一個Segment,一個 Segment 由多個權限相同的 Section 構成。 不巧的是,“Segment”也被翻譯為“段”,但這里的段(Segment)是針對加載和執行的過程。 在 Linux 下,相信很多讀者都遇到過一種叫做`Segment fault(段錯誤)`的錯誤,這種錯誤發生在程序執行期間,在編譯和鏈接時無法檢測,一般都是代碼的權限不足導致的。例如: ~~~ #include <stdio.h> char *str = "c.biancheng.net"; int main(){ str[1] = '@'; return 0; } ~~~ 程序執行到 6 行時就會出現“Segment fault(段錯誤)”,這是因為字符串 str 保存在地址空間的常量區,只能讀取,不能寫入,而修改字符串顯然是越權操作。 在目標文件中,`段表(Section Table)`用來描述各個 Section 的信息,包括它的名字、長度、在文件中的偏移、讀寫權限等,通過段表可以詳細地了解目標文件的結構。 而在可執行文件中,段表被刪除了,取代它的是`程序頭表(Program Header Table)`;程序頭表用來描述各個 Segment 的信息,包括它的類型、偏移、在進程虛擬地址空間中的起始地址、物理裝載地址、長度、權限等。操作系統就是根據程序頭表將可執行文件加載到內存,并為各個 Segment 分配內存空間、確定起止地址。 也就是說,可執行文件不再關注具體的文件結構,而是關注程序的加載和執行過程。 由于可執行文件在加載時實際上是被映射的虛擬地址空間,所以可執行文件很多時候又被叫做映像文件(Image) # 段(Section)的合并 編譯器生成的是目標文件,而我們最終需要的是可執行文件,鏈接(Linking)的作用就是將多個目標文件合并成一個可執行文件。 在鏈接過程中,鏈接器會將多個目標文件中的代碼段、數據段、調試信息等合并成可執行文件中的一個段。段的合并僅僅是一個簡單的疊加過程,如下圖所示: ![](https://box.kancloud.cn/5c3fa0e859b8efc3e1efedb1ebafe909_495x441.png) 除了合并有用的段(例如代碼段、數據段等),鏈接器還會刪除多余的段(例如重定位段、段表等),增加其他段(例如程序頭表等)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看