linux 如何執行乙個可執行檔案

2021-06-22 19:56:37 字數 2665 閱讀 8306

本文只為整理思路,供自己日後參考。現在就從從乙個執行檔案a.out的執行開始,自上而下地分析linux是如何執行乙個執行檔案的。

1、首先,需要了解一下a.out這個目標檔案。a.out在linux下是elf(executable linkable format)檔案格式,該目標檔案由乙個檔案頭、**段、資料段(已初始化)、從定位資訊區、符號表及符號名字字串構成,如下左圖所示,經過鏈結後生成執行檔案如下右圖所示,需要說明的是1).bss段在目標檔案和執行檔案中並不占用檔案的空間,但是它在載入時占用位址空間;2)鏈結後各個段在虛擬空間上的位址就確定了,並且linux下,elf可執行檔案預設從位址0x080480000開始分配。

我們知道在linux下執行乙個程式只要在shell中執行 ./a.out 這個命令就ok了,剩下的事情作業系統會替我們完成。但是作業系統到底做了什麼,它是怎麼做的呢,接下來就來解析一下。

2、linux系統中每個程式都執行在乙個程序上下文中,這個程序上下文有自己的虛擬位址空間。當shell執行乙個程式時,父shell程序生成乙個子程序,它是父程序的乙個複製品。子程序通過execve系統呼叫啟動載入器。載入器刪除子程序已有的虛擬儲存段,並建立一組新的**、資料、堆、棧段,新的堆和棧被初始化為零。通過將虛擬位址空間中的頁對映到可執行檔案的頁大小組塊,新的**和資料段被初始化為可執行檔案的內容,最後將cup指令暫存器設定成可執行檔案入口,啟動執行。

執行完上述操作後,其實可執行檔案的真正指令和資料都沒有別裝入記憶體中。作業系統只是通過可執行檔案頭部的資訊建立起可執行檔案和程序虛擬記憶體之間的對映關係而已。現在程式的入口位址為0x08048000,剛好是**段的起始位址。當cpu打算執行這個位址的指令時,發現頁面0x8048000~0x08049000(乙個頁面一般是4k)是個空頁面,於是它就認為是個頁錯誤。此時作業系統根據虛擬位址空間與可執行檔案間的對映關係找到頁面在可執行檔案中的偏移,然後在物理記憶體中分配乙個物理頁面,並在虛擬位址頁面與物理頁面間建立對映,最後把檔案中頁面拷貝到物理頁面,程序重新開始執行。該過程如下圖所示:

3、這裡比較難理解的就是這個分頁機制,講到分頁機制,就不得不提linux的分段與分頁機制,這也是這篇文章的重點。我們先來看一張圖:

這張圖展示了虛擬位址進過分段、分頁機制後轉化成實體地址的簡單過程。其實分段機制是intel晶元為相容以前產品而保留下來的,然後linux中弱化了這一機制。下面我們先簡單介紹一下分段機制:

分段提供了隔絕各個**、資料和堆疊區域的機制,它把處理器可定址的線性位址空間劃分成一些較小的稱為段的受保護位址空間區域。如果處理器中有多個程式在執行,那麼每個程式可分配各自的一套段。此時處理器就可以加強這些段之間的界限,並確保乙個程式不會通過訪問另乙個程式的段而干擾程式的執行。為了定位指定段中的乙個位元組,程式必須提供乙個邏輯位址,該位址包括乙個段選擇符和乙個偏移量。實模式下,段值還是可以看作位址的一部分,段值位***xh表示以***x0h開始的一段記憶體。而保護模式下,段值僅僅變成了乙個索引,只想乙個資料結構的乙個表項,該表項中定義了段的起始位址、界限、屬性等內容。cs、ds等暫存器中存的就是這個段選擇符,用段選擇符中的段索引在gdt或ldt表中定位相應的段描述符,把段描述符中取得的段基位址加上偏移量,就形成了乙個線性位址。

得到了線性位址之後,我們再來看看分頁機制如何把它轉換成實體地址。處理器分頁機制會把線性位址空間(段已對映到其中)劃分成頁面,然後這些線性位址空間頁面被對映到實體地址空間的頁面上。分頁與分段最大的不同之處在於分頁是用來固定長度的頁面(一般為4kb)。如果僅適用分段位址轉換,那麼儲存在物理記憶體中的乙個資料結構將包含器所有部分。但如果適用了分頁,那麼乙個資料結構就可以一部分儲存在物理記憶體中,而另一部分儲存在磁碟中。

處理器把線性位址轉換成實體地址和用於產生頁錯誤異常的資訊包含在儲存與記憶體中的頁目錄和頁表中。也變可看作簡單的4k為單位的實體地址陣列。線性位址的高20位構成這個陣列的引索值,用於選擇對應頁面的物理基位址。線性位址的低12位給出 了頁面中的偏移量。頁表中的頁表項大小為32位。由於只需要其中20位來存放頁面的物理基位址,因此剩下的12位可用於存放諸如頁面是否存在等屬性資訊。如果線性位址引索的頁表項被標註為存在,我們就從頁面中取得實體地址。如果表項中不存在,那麼訪問對應物理頁面時就會產生異常。

頁表含有2^20(1m)個表項,而每項占用4個位元組。如果作為乙個表來存放的話,最多將占用4mb記憶體。因此為了減少記憶體佔用量,80x86適用了兩級表。由此,高20位線性位址到實體地址的轉換也被分成兩步進行,每部適用其中10個位元。

第一級表稱為頁目錄。它被存放在1頁4k 頁面中,具有2^10(1k)個4位元組長度的表項。這些表項指向二級表。它們由線性位址最高10位作為引索。

第二級表稱為頁表,長度也是1個頁面。線性位址高10位獲取指向第二級頁表的指標,再加上中間10位,就可以在相應頁表中獲得實體地址的高20位。而為位址的低12位就是線性位址的低12,這樣就組成了乙個完整的32位實體地址。分段、分頁的整個過程可見下面這張圖:

linux 執行可執行檔案

1 首先,需要了解一下a.out這個目標檔案。a.out在linux下是elf executable linkable format 檔案格式,該目標檔案由乙個檔案頭 段 資料段 已初始化 從定位資訊區 符號表及符號名字字串構成,如下左圖所示,經過鏈結後生成執行檔案如下右圖所示,需要說明的是1 bs...

linux編譯和執行乙個可執行檔案初學篇

在大公司上班,系統中的模組都有明確的分工,一直以來也只是熟悉自己負責的那一點點東西,感覺就是井底之蛙。所以希望自己能夠靜下心來,學一點,多學一點。本篇作為乙個學習的起點,先學習如何編譯和執行乙個可執行檔案。測試 如下 include int main int argc,char argv int i...

Linux下執行可執行檔案

我們通常會為計算機配置環境變數 path,echo path 檢視當前的環境變數包含的目錄。這些目錄下的可執行檔案就無需輸入完整路徑來執行,直接輸入命令就行,我們shell中常使用的一些linux命令,例如man,cat等的目錄都被包含在該path目錄中,所以直接在shell中輸入這些命令就可以。即...