iOS開發(fā)中的內存分配與分區(qū)
內存
關于RAM&ROM
RAM與ROM就是具體的存儲空間缭召,統(tǒng)稱為存儲器逆日。
RAM(random access memory):運行內存,CPU可以直接訪問室抽,讀寫速度非常快坪圾,但是不能掉電存儲。它又分為:
動態(tài)DRAM兽泄,速度慢一點,需要定期的刷新(充電)胃珍,我們常說的內存條就是指它,價格會稍低一點堂鲜,手機中的運行內存也是指它。
靜態(tài)SRAM缔莲,速度快,我們常說的一級緩存痴奏,二級緩存就是指它,當然價格高一點擅憔。
ROM(read only memory):存儲性內存,可以掉電存儲暑诸,例如SD卡辟灰、Flash(機械磁盤也可以簡單的理解為ROM)个榕。用的多的:NandFlash芥喇,還有NorFlash,現在用的已經比較少了(兩者主要區(qū)別是前者空間大械馆,便宜,后者可以直接運行程序霹崎,讀取速度快)冶忱。
由于RAM類型不具備掉電存儲能力(即一停止供電數據全沒了仿畸,從新上電后全是亂碼朗和,所以需要初始化)簿晓,所以app程序一般存放于ROM中。RAM的訪問速度要遠高于ROM憔儿,價格也要高。
RAM與ROM協(xié)同工作
由于RAM不能掉電存儲,所以我們的APP程序耀里,刷機包拾氓,下載的文件等等冯挎,都是在ROM里面存儲的咙鞍。
手機里面使用的ROM基本都是NandFlash蹭沛,CPU是不能直接訪問的绍哎,而是需要文件系統(tǒng)/驅動程序(嵌入式中的EMC)將其讀到RAM里面眷蜈,CPU才可以訪問畴蹭。另外朗恳,RAM的速度也比NandFlash快湿颅。
內存分區(qū):可以分為5個區(qū)
說到內存分區(qū)僻肖,內存即指的是RAM。
棧區(qū)(stack): 這個一般由編譯器操作劝堪,或者說是系統(tǒng)管理,會存一些局部變量秒啦,函數跳轉跳轉時現場保護(寄存器值保存于恢復)搀玖,這些系統(tǒng)都會幫我們自動實現余境,無需我們干預灌诅。 所以大量的局部變量,深遞歸猜拾,函數循環(huán)調用都可能耗盡棧內存而造成程序崩潰 。
堆區(qū)(heap): 一般由程序員管理顽聂,比如alloc申請內存,free釋放內存紊搪。我們創(chuàng)建的對象也都放在這里。
全局區(qū)(靜態(tài)區(qū) static):全局變量和靜態(tài)變量的存儲是放在一塊的耀石,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域奔浅。程序結束后有系統(tǒng)釋放。注意:在嵌入式系統(tǒng)中全局區(qū)又可分為未初始化全局區(qū):.bss段和初始化全局區(qū):data段汹桦。舉例:int a;未初始化的鉴裹。int a = 10;已初始化的。
常量區(qū):常量字符串就是放在這里的径荔,還有const常量。
代碼區(qū):存放代碼总处,app程序會拷貝到這里,程序不是在ROM里面存儲嗎鹦马?看下面的舉例
圖中各個區(qū)并不連續(xù)
701177-1e5ef45ec9480700.png
memZonepic01.png
程序運行舉例(CPU RAM ROM之間協(xié)同)
首先了解下:虛擬內存與物理內存。
手機上的所有程序都是依托操作系統(tǒng)菱肖,運行在虛擬內存上的,每一個APP都會以為自己擁有所有的虛擬內存稳强。比如一個手機和悦,它是32位操作系統(tǒng)(一般也是32位總線)退疫,真實的物理內存為2G鸽素,那么他的尋址空間為4G(2的32次方),對于APP來說付鹿,它覺得自己擁有4G的內存,雖然這是不可能的(或者說同一時間是不可能的)俊抵,但是坐梯,操作系統(tǒng)只要保證APP當時用到的地址空間有真實的物理地址對應就可以徽诲,APP也不需要知道那對應的2G真實物理內存具體在哪里吵血。不要求4G的虛擬內存同一時間都有真實的物理內存相對應,當然那也是不可能的蹋辅,因為只有2G物理內存。
在下面的舉例中秩命,只考慮虛擬內存
當我們點擊手機屏幕APP的Icon啟動一個APP(例如微信)時褒傅,操作系統(tǒng)會為微信開辟4G的虛擬內存空間(開辟真實的物理內存弃锐,對應一部分到4G的虛擬內存),操作系統(tǒng)會把存儲在ROM里面微信的部分代碼(受空間所限殿托,不可能全部拷貝)霹菊,拷貝到上一步開辟的4G內存空間的代碼區(qū),如上圖支竹,然后CPU就可以訪問RAM來運行微信的程序了 旋廷。
假設通過微信我們下載了一個100M的視頻,那么會從服務器一點一點的下載到RAM唾戚,然后再從RAM寫到ROM存儲柳洋。這樣才能保證,我們關掉微信并再次打開時視頻還在叹坦。假設隔一段時間熊镣,我們要看視頻,程序會將它從ROM讀到RAM然后解碼播放募书。
701177-4e31e3404a0b5d0c.png
memZonepic002.png
編程注意
當一個app啟動后,代碼區(qū)莹捡,常量區(qū)鬼吵,全局區(qū)地址已固定,因此指向這些區(qū)的指針不會為空而產生崩潰性的錯誤篮赢。而堆區(qū)和棧區(qū)是時時刻刻變化的(堆的創(chuàng)建銷毀齿椅,棧的彈入彈出)琉挖,所以當使用一個指針指向這兩個區(qū)里面的內存時,一定要注意內存是否已經被釋放涣脚,否則會產生程序崩潰(編程中很常見)示辈。