程序員的自我修養--可執行文件的裝載與進程

進程的虛擬地址空間

  1. C語言指針大小的位數與虛擬地址空間的地址位數相同,即32位平臺下進程的虛擬地址空間爲4G
  2. 由於程序在運行是處於操作系統的監管下,進程的虛擬地址空間都在操作系統的掌握中,只能使用操作系統分配給進程的地址。如果訪問未經允許的地址,將會強制結束進程。一般在linux上回出現Segmentation fault
  3. 在32位平臺中,整個4 GB被劃分成兩部分,其中操作系統本身用去了一部分:從地址0xC00000000到0xFFFFFFFF,共1 GB。剩下的從0x00000000地址開始到0xBFFFFFFF共3 GB的空間都是留給進程使用的。那麼從原則上講,我們的進程最多可以使用3 GB的虛擬空間,也就是說整個進程在執行的時候,所有的代碼、數據包括通過C語言malloc()等方法申請的虛擬空間之和不可以超過3 GB
  4. 通過窗口映射的方式將高於4G的物理內存進程的虛擬地址空間中,linux中採用mmap的系統調用實現

裝載方式

  1. 動態裝入:根據程序的局部性原理,將程序最常用的部分裝入內存,不太常用的放到磁盤中
  2. 覆蓋轉入:程序員編寫覆蓋管理器,手工將程序分割成若干塊,然後編寫一個小的輔助代碼來管理這些模塊何時應該駐留內存而何時應該被替換掉
  3. 頁映射:是虛擬存儲機制的一部分,物理頁與虛擬空間中的頁大小相同,通過存儲管理器進行調度虛擬頁到物理頁中

從操作系統角度看可執行文件的裝載

1.進程的建立的三步:

  • 創建一個獨立的虛擬地址空間(創建映射函數需要的數據結構,建立虛擬空間與物理內存映射關係)
  • 讀取可執行文件頭,並且建立虛擬空間與可執行文件的映射關係(建立虛擬空間與可執行文件之間的關係)

當程序發生頁錯誤的時候,操作系統將從物理內存中申請物理頁空間,然後將“缺頁”從內存中讀到磁盤中,設置虛擬頁與物理頁之間的映射關係。當發生缺頁錯誤的時候,通過虛擬地址空間與可執行文件之間的映射關係獲取需要在相應頁在可執行文件中的具體位置

  • 將CPU的指令寄存器設置成可執行文件的入口地址,啓動運行

2.頁錯誤

當發生頁錯誤的時候,操作系統首先找到空頁面所在的VMA,計算出相應頁面在可執行文件中的偏移量,在物理內存中分配一個物理頁面,將虛擬頁面與物理頁面之間建立映射關係,把控制權交還給進程,進程從剛纔頁錯誤的位置開始執行。

進程虛存空間分佈

1.ELF文件鏈接視圖和執行視圖
在ELF文件被映射的時候。每個section在映射的時候長度都是該系統頁長度的整數倍,如果不是,則多餘的部分將會佔用一個頁,這種情況就會導致大量的內存碎片。

爲了解決上述問題,操作系統將相同權限的section合併到一起當做一個segment進行映射,在映射之後在進程的虛擬地址空間中只有一個對應的VMA,在ELF文件中專門有一個程序頭表用來保存Segment信息。

這裏寫圖片描述

2.堆和棧
操作系統通過使用VMA來管理虛擬地址空間,除了用來映射各個segment,還可以用來管理棧、堆等空間。例如如下的elf文件和虛擬地址空間之間的映射關係:
這裏寫圖片描述

上圖中需要注意的是對於“.bss”和“__libcfreeres_ptrs”部分沒有映射到文件,通過do_brk()將“.bss”和“__libcfreeres_ptrs”剩餘部分映射到堆棧中。

3.堆空間的最大申請數量
具體數值是受到操作系統版本、程序大小、程序棧數量等的限制,甚至有些每次運行的結果不同。

4.段地址對齊
由於段地址對齊的方式會在文件段的內部出現很多的碎片,導致磁盤的浪費。操作系統通過讓各個segment接壤的部分共享一個物理頁面,將該頁面分別映射兩次來解決,如下圖:
這裏寫圖片描述

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