標籤:
iOS開發中的記憶體配置與分區 關於RAM&ROM
RAM與ROM就是具體的儲存空間,統稱為儲存空間。
RAM(random access memory):運行記憶體,CPU可以直接存取,讀寫速度非常快,但是不能掉電儲存。它又分為:
ROM(read only memory):儲存性記憶體,可以掉電儲存,例如SD卡、Flash(機械磁碟也可以簡單的理解為ROM)。用的多的:NandFlash,還有NorFlash,現在用的已經比較少了(兩者主要區別是前者空間大,便宜,後者可以直接運行程式,讀取速度快)。
由於RAM類型不具備掉電儲存能力(即一停止供電資料全沒了,從新上電後全是亂碼,所以需要初始化),所以app程式一般存放於ROM中。RAM的訪問速度要遠高於ROM,價格也要高。
RAM與ROM協同工作
由於RAM不能掉電儲存,所以我們的APP程式,刷機包,下載的檔案等等,都是在ROM裡面儲存的。
手機裡面使用的ROM基本都是NandFlash,CPU是不能直接存取的,而是需要檔案系統/驅動程式(嵌入式中的EMC)將其讀到RAM裡面,CPU才可以訪問。另外,RAM的速度也比NandFlash快。
記憶體分區:可以分為5個區
說到記憶體分區,記憶體即指的是RAM。
棧區(stack): 這個一般由編譯器操作,或者說是系統管理,會存一些局部變數,函數跳轉跳轉時現場保護(寄存器值儲存於恢複),這些系統都會幫我們自動實現,無需我們幹預。 所以大量的局部變數,深遞迴,函數迴圈調用都可能耗盡棧記憶體而造成程式崩潰 。
堆區(heap): 一般由程式員管理,比如alloc申請記憶體,free釋放記憶體。我們建立的對象也都放在這裡。
全域區(靜態區 static):全域變數和靜態變數的儲存是放在一塊的,初始化的全域變數和靜態變數在一塊地區, 未初始化的全域變數和未初始化的靜態變數在相鄰的另一塊地區。程式結束後有系統釋放。注意:在嵌入式系統中全域區又可分為未初始化全域區:.bss段和初始化全域區:data段。舉例:int a;未初始化的。int a = 10;已初始化的。
常量區:常量字串就是放在這裡的,還有const常量。
代碼區:存放代碼,app程式會拷貝到這裡,程式不是在ROM裡面儲存嗎?看下面的舉例
圖中各個區並不連續
memZonepic01.png程式運行舉例(CPU RAM ROM之間協同)
首先瞭解下:虛擬記憶體與實體記憶體。
手機上的所有程式都是依託作業系統,運行在虛擬記憶體上的,每一個APP都會以為自己擁有所有的虛擬記憶體。比如一個手機,它是32位作業系統(一般也是32位匯流排),真實的實體記憶體為2G,那麼他的定址空間為4G(2的32次方),對於APP來說,它覺得自己擁有4G的記憶體,雖然這是不可能的(或者說同一時間是不可能的),但是,作業系統只要保證APP當時用到的地址空間有真實的物理地址對應就可以,APP也不需要知道那對應的2G真實實體記憶體具體在哪裡。不要求4G的虛擬記憶體同一時間都有真實的實體記憶體相對應,當然那也是不可能的,因為只有2G實體記憶體。
在下面的舉例中,只考慮虛擬記憶體
當我們點擊手機螢幕APP的Icon啟動一個APP(例如)時,作業系統會為開闢4G的虛擬記憶體空間(開闢真實的實體記憶體,對應一部分到4G的虛擬記憶體),作業系統會把儲存在ROM裡面的部分代碼(受空間所限,不可能全部拷貝),拷貝到上一步開闢的4G記憶體空間的代碼區,如,然後CPU就可以訪問RAM來啟動並執行程式了 。
假設通過我們下載了一個100M的視頻,那麼會從伺服器一點一點的下載到RAM,然後再從RAM寫到ROM儲存。這樣才能保證,我們關掉並再次開啟時視頻還在。假設隔一段時間,我們要看視頻,程式會將它從ROM讀到RAM然後解碼播放。
memZonepic002.png編程注意
當一個app啟動後,代碼區,常量區,全域區地址已固定,因此指向這些區的指標不會為空白而產生崩潰性的錯誤。而堆區和棧區是時時刻刻變化的(堆的建立銷毀,棧的彈入彈出),所以當使用一個指標指向這兩個區裡面的記憶體時,一定要注意記憶體是否已經被釋放,否則會產生程式崩潰(編程中很常見)。
iOS開發中的記憶體配置與分區