編譯後的程式是如何在作業系統(linux)中執行的,虛擬地址空間到實際實體記憶體的訪問
Linux中,每個程序通過一個task_struct結構體描述,每個程序地址虛擬空間通過一個mm_struct描述,c語言中每個段空間通過vm_area_struct描述,關係如下,
當執行一個程式時,linux建立一個程序,通過sys_exec()將該程式的內容(程式編譯後產生的是虛擬地址空間)對映到程序的虛擬地址空間中而不是實體記憶體中,生成一組vm_area_struct資料結構用來表示可執行程式的資訊。具體步驟如下:
(1)建立一組vm_area_struct;
(2)將程式編譯的起始地址儲存到vm_start和vm_end中;
(3)將磁碟file控制代碼儲存在vm_file
(4)將對應段在磁碟file中的偏移值儲存在vm_pgoff中;
(5)將操作該磁碟file的磁碟操作函式儲存在vm_ops中;
(6)假設程式有一條指令需要讀取地址vm_start~vm_end之間的某內容,例如:
mov[0x08000011],%eax; 那麼將會執行如下序列:
(1)cpu依據CR3(current->pgd)找到0x08000011地址對應的pgd[i],由於該pgd[i]內容保持初始化狀態即為0,導致cpu page fault;
(2)呼叫do_page_fault()系統呼叫,為pgd[i]在記憶體中分配一個頁表,並該讓頁表指向它,如下圖所示:
(3)為pte[j]
1 分配實體記憶體頁
2 從磁碟檔案中將內容讀取到實體記憶體頁面中
總結,執行程式過程中,如果當前指令或資料在虛擬地址空間中,實際沒有在實體記憶體中,將發生缺頁錯誤,這時作業系統再從實體記憶體分配一個空閒的物理頁,並將虛擬地址頁對應的資料從磁碟載入到該物理頁中,並建立頁表項和頁幀的對映關係。假設程式佔用記憶體非常大,隨著程序的執行,缺頁錯誤不斷產生,作業系統會響應每個缺頁錯誤並未程序分配實體記憶體頁框。但是實體記憶體是有限的,全部實體記憶體都分配給程序後,如果程序繼續丟擲缺頁錯誤,此時作業系統就會採用