iOS內存不夠怎麼辦?-底層原理

在早期的計算機中,程序是直接運行在物理內存上的,也就是說:程序在運行時訪問的地址就是物理地址。這樣也就是單運行的時候沒有什麼問題!但是,計算機會有多到程序、分時系統和多任務,當咱們可以同時運行多個程序時,CPU的利用率將會比較高。那麼有一個很是嚴重的問題:如何將計算機的有限的物理內存分配給多個程序使用程序員

假設咱們計算有128MB內存,程序A須要10MB,程序B須要100MB,程序C須要20MB。若是咱們須要同時運行程序A和B,那麼比較直接的作法是將內存的前10MB分配給程序A,10MB~110MB分配給B。數組

但這樣作,會形成如下問題:函數

  • 當多個程序須要運行時,必須保證這些程序用到的內存總量要小於計算機實際的物理內存的大小。學習

  • 進程地址空間不隔離,因爲程序是直接訪問物理內存的,因此每個進程均可以修改其餘進程的內存數據,設置修改內核地址空間中的數據,因此有些惡意程序能夠隨意修改別的進程,就會形成一些破壞操作系統

  • 內存使用效率低 內存空間不足,就須要將其餘程序展現拷貝到硬盤當中,而後將新的程序裝入內存。然而因爲大量的數據裝入裝出,內存的使用效率會很是低code

  • 程序運行的地址不肯定;由於內存地址是隨機分配的,因此程序運行的地址也是不正確的cdn

解決這幾個問題的思路就是使用咱們很是牛逼的方法:增長中間層 - 即便用一種間接的地址訪問方式。blog

把程序給出的地址看作是一種虛擬地址,而後經過某種映射,將這個虛擬地址轉化到實際的物理地址。這樣,只須要控制好映射過程,就能保證程序所能訪問的物理內存區域跟別的程序不重疊,達到空間隔離的效果。進程

隔離

普通的程序它只須要一個簡單的執行環境一個單一的地址空間有本身的CPU。 地址空間比較抽象,若是把它想象成一個數組,每個數組是一字節,數組大小就是地址空間的長度,那麼32位的地址空間大小就是2^32=4294967296字節,即4G,地址空間有效位是0x00000000~0xFFFFFFFF。 地址空間分爲兩種:內存

  • 物理空間:就是物理內存。32位的機器,地址線就有32條,物理空間4G,但若是隻裝有512M的內存,那麼實際有效的空間地址就是0x00000000~0x1FFFFFFF,其餘部分都是無效的。

  • 虛擬空間:每一個進程都有本身獨立的虛擬空間,並且每一個進程只能訪問本身的空間地址,這樣就有效的作到了進程隔離。

分段

基本思路: 把一段與程序所須要的內存空間大小的虛擬空間映射到某個地址空間。虛擬空間的每一個字節對應物理空間的每一個字節。這個映射過程由軟件來完成。

好比A須要10M,就假設有0x000000000x00A00000大小的虛擬空間,而後從物理內存分配一個相同大小的空間,好比是0x001000000x00B00000。操做系統來設置這個映射函數,實際的地址轉換由硬件完成。若是越界,硬件就會判斷這是一個非法訪問,拒絕這個地址請求,並上報操做系統或監控程序。

這樣一來利用:分段的方式能夠解決以前的個(地址空間不隔離)和第三個問題(程序運行地址不肯定)

  • 首先作到了地址隔離,由於A和B被映射到了兩塊不一樣的物理空間,它們之間沒有任何重疊,若是A訪問虛擬空間的地址超過了0x00A00000這個範圍,硬件就會判斷這是一個非法的訪問,並將這個請求報告給操做系統或者監控程序,由它決定如何處理。

  • 再者,對於每一個程序來講,不管它們被分配到地址空間的哪個區域,對於程序來講都是透明的,它們不須要關心物理地址的變化,它們只要按照從地址0x000000000x00A00000來編寫程序、放置變量,因此程序不須要重定位。

第二問題內存使用效率問題依舊沒有解決。

可是分段的方法沒有解決內存使用效率的問題。分段對於內存區域的映射仍是按照程序爲單位,若是內存不足,被換入換出的磁盤的都是整個程序,這樣勢必會形成大量的磁盤訪問操做,從而嚴重影響速度,這種方法仍是顯得粗糙,粒度比較大。事實上根據程序的局部性原理,當一個程序正在運行時,在某個時間段內,它只是頻繁用到了一小部分數據,也就是說,程序的不少數據其實在一個時間段內是不會被用到的。人們很天然地想到了更小粒度的內存分割和映射方法,使得程序的局部性原理獲得充分利用,大大提升了內存的使用率。這種方法就是分頁。

分頁

分頁的基本方法是把地址空間人爲得等分紅固定大小的頁,每個頁的大小由硬件決定,或硬件支持多種頁的大小,由操做系統選擇決定頁的大小。 目前幾乎全部PC的操做系統都是用4KB大小的頁。咱們使用的PC機是32位虛擬地址空間,也就是4GB,按4KB分頁,總共有1048576個頁。

那麼,當咱們把進程的虛擬地址空間按頁分割,把經常使用的數據和代碼裝載到內存中,把不經常使用的代碼和數據保存在磁盤裏,當須要用到的時候再把它們從磁盤裏取出便可。圖中的線表示映射關係,咱們能夠看到虛擬空間有些頁被映射到同一個物理頁,這樣就能夠實現內存共享。 虛擬頁,物理頁,磁盤頁根據內存空間不同而區分

咱們能夠看到Process 1 的VP2和VP3不在內存中,可是當進程須要用到這兩個頁的時候,硬件就會捕獲到這個消息,就是所謂的頁錯誤(Page Fault),而後操做系統接管進程,負責將VP2和VP3從磁盤讀取出來裝入內存,然都將內存中的這兩個頁和VP2和VP3創建映射關係。以頁爲單位存取和交換數據很是方便,硬件自己就支持這種以頁爲單位的操做方式。

  • 保護頁也是頁映射的目的之一,簡單地說就是每一個頁能夠設置權限屬性,誰能夠修改,誰能夠訪問,並且只有操做系統有權修改這些屬性,那麼操做系統就能夠作到保護本身和保護進程。

  • 虛擬存儲的實現須要硬件支持,幾乎全部CPU都採用稱爲MMU的部件來進行頁的映射:

在頁映射模式下,CPU發出的是Virtual Address,即咱們程序看到的是虛擬地址。通過MMU轉換之後就變成了Physical Address。通常MMU集成在CPU內部,不會以獨立的部件存在。

這篇文章是底層編譯連接的開門紅,這裏很是感謝《程序員的自我修養-連接、裝載與庫》這本書的大力分享,強烈推薦學習

相關文章
相關標籤/搜索