專(zhuān)利名稱(chēng):一種提高內(nèi)存池利用率的方法
技術(shù)領(lǐng)域:
本發(fā)明屬于嵌入式實(shí)時(shí)操作系統(tǒng)領(lǐng)域,具體地說(shuō),涉及一種提高嵌入式 實(shí)時(shí)操作系統(tǒng)內(nèi)存池利用率的方法。
背景技術(shù):
嵌入式軟件的應(yīng)用愈來(lái)愈廣泛,而在滿足系統(tǒng)實(shí)時(shí)性要求的前提下,如 何提高內(nèi)存分配的快速性、可靠性、高效性,是嵌入式軟件系統(tǒng)需要重點(diǎn)研 究的一個(gè)課題。嵌入式軟件內(nèi)存分配的快速性從嵌入式系統(tǒng)對(duì)實(shí)時(shí)性的要求 出發(fā),要求內(nèi)存在分配過(guò)程中盡可能的快,因此在嵌入式系統(tǒng)中,不可能采 用通用操作系統(tǒng)中復(fù)雜而繁瑣的內(nèi)存分配策略, 一般都采用簡(jiǎn)單、快速的內(nèi)存分配方案;嵌入式軟件內(nèi)存分配的可靠性則要求內(nèi)存分配的請(qǐng)求必須得到 滿足,如果分配失敗的話可能會(huì)帶來(lái)突難性的后果;而嵌入式軟件內(nèi)存分配 的高效性,則要求內(nèi)存分配盡可能地少浪費(fèi)。目前,在嵌入式軟件開(kāi)發(fā)中,特別是在諸如電信、信息家電這些行業(yè), 由于對(duì)內(nèi)存的申請(qǐng)和釋放比較頻繁, 一般采用的內(nèi)存分配方法是使用內(nèi)存分 塊管理的內(nèi)存池方式。它的技術(shù)方案如圖l所示。為了避免由于內(nèi)存頻繁申請(qǐng)和釋放而導(dǎo)致內(nèi)存碎片,通用的內(nèi)存池管理 方式是首先配置各種大小的內(nèi)存塊的數(shù)量,比如21字節(jié)大小的內(nèi)存塊111個(gè), 22字節(jié)大小的內(nèi)存塊11個(gè),以此類(lèi)推,2"字節(jié)大小的內(nèi)存塊f個(gè)(其中m、 n、 f均為任意整數(shù)),同時(shí)在內(nèi)存頭中保存每個(gè)內(nèi)存塊的信息。然后在空閑 內(nèi)存中分配一個(gè)大內(nèi)存,專(zhuān)門(mén)用于滿足用戶的內(nèi)存申請(qǐng)需求,該內(nèi)存池大小 為各種大小的內(nèi)存塊大小的總和,即(2、m + 22 xn+... + 2nxf +所有內(nèi)存頭大小)的值。在進(jìn)行內(nèi)存申請(qǐng)時(shí),根據(jù)申請(qǐng)內(nèi)存的大小在相應(yīng)的內(nèi)存池中尋找滿足大小需要的內(nèi)存塊,如果用戶申請(qǐng)的內(nèi)存是在2q"-2q這樣一個(gè)區(qū)間中(q為一個(gè)確定的整數(shù),滿足2q"〈申請(qǐng)內(nèi)存大小<=2q),則取一個(gè)空閑的2q大小的內(nèi)存塊分配給應(yīng)用;內(nèi)存釋放是根據(jù)內(nèi)存塊的指針找到相應(yīng)的頭,再將其標(biāo)記為自由內(nèi)存并歸還給相應(yīng)的緩沖池的過(guò)程。這種通用的內(nèi)存池管理方法針對(duì)頻繁申請(qǐng)和釋放的內(nèi)存,可以高效、可 靠地滿足應(yīng)用需要,同時(shí)也可以較好的避免內(nèi)存碎片的問(wèn)題。因此在目前的 嵌入式軟件開(kāi)發(fā)中,有很大范圍的應(yīng)用。但是,這種通用的內(nèi)存池管理方式對(duì)內(nèi)存池中內(nèi)存塊的大小和數(shù)量的分 配需要嵌入式軟件開(kāi)發(fā)人員具有比較高的經(jīng)驗(yàn)值以及在具體的嵌入式軟件應(yīng)用中反復(fù)統(tǒng)計(jì)、調(diào)試,得到一個(gè)相對(duì)合理的數(shù)值。比如在VxWorks操作 系統(tǒng)中,User Reserved (等于sysPhsMemTop( ) - sysMemTop())的內(nèi)存 是用戶保留區(qū)域,可以分配作為總的內(nèi)存池大小。但是,這User Reserved 大小的內(nèi)存池分配多少個(gè)2'大小的內(nèi)存塊,多少個(gè)22大小的內(nèi)存塊,...多 少個(gè)2n大小的內(nèi)存塊呢?現(xiàn)在的做法是由設(shè)計(jì)人員憑借經(jīng)驗(yàn)值進(jìn)行初步估 計(jì),然后在測(cè)試中進(jìn)行調(diào)試決定。這樣,導(dǎo)致該內(nèi)存池的大小和數(shù)量值需要 較長(zhǎng)一段時(shí)間才能趨于穩(wěn)定,而且可能導(dǎo)致部分內(nèi)存池的利用率不高,甚至 會(huì)得不到使用;而某些大小的內(nèi)存池則由于數(shù)量太少導(dǎo)致內(nèi)存申請(qǐng)失敗。對(duì)于這種申請(qǐng)2q(q為一個(gè)確定的整數(shù))大小的內(nèi)存塊,由于2q內(nèi)存塊數(shù)量配置太少導(dǎo)致內(nèi)存申請(qǐng)可能失敗的解決辦法,目前通用的辦法如下1、 申請(qǐng)使用更大一些的內(nèi)存塊,如對(duì)2q大小的內(nèi)存塊,使用比其大一 級(jí)的內(nèi)存塊2q"。該方法實(shí)現(xiàn)簡(jiǎn)單方便,在內(nèi)存池足夠大的情況下是簡(jiǎn)單有效的;但是在嵌入式系統(tǒng)中,由于需要考慮內(nèi)存資源的成本,內(nèi)存足夠大表明成本還可以進(jìn)一步降低。這種方法,可能直接導(dǎo)致至少2q"-2q大小的內(nèi)存浪費(fèi)(q值越大,浪費(fèi)越大),這往往是被嵌入式系統(tǒng)設(shè)計(jì)所不能接受的。2、 使用伙伴(buddy)系統(tǒng)管理存儲(chǔ)區(qū)方法。當(dāng)2q大小的內(nèi)存塊申請(qǐng)不到時(shí),使用比其大一級(jí)的內(nèi)存塊2q",但其將分成兩個(gè)2q大小的內(nèi)存塊。該方法可以避免方法1的缺陷,有效避免內(nèi)存浪費(fèi)。但是其引入的buddy算 法,直接導(dǎo)致內(nèi)存申請(qǐng)和釋放的復(fù)雜性,降低了內(nèi)存申請(qǐng)和釋放的效率。發(fā)明內(nèi)容本發(fā)明所要解決的技術(shù)問(wèn)題在于提供一種新的提高內(nèi)存池利用率的方 法,這種方法不僅能夠充分利用目前通用內(nèi)存池高效、可靠、不產(chǎn)生內(nèi)存碎 片等優(yōu)點(diǎn),還可以有效地提高內(nèi)存池中各個(gè)內(nèi)存塊的利用率,大大降低通用 內(nèi)存池可能存在的內(nèi)存塊要么得不到使用,要么不夠使用的情況。本發(fā)明的一種提高內(nèi)存池利用率的方法包括如下步驟步驟l:在內(nèi)存資源中分配一個(gè)大內(nèi)存池,用于用戶申請(qǐng)或釋放內(nèi)存; 設(shè)置一個(gè)指針變量ptAddrToUse,用于指示該內(nèi)存池中可以用以分配內(nèi)存塊 的起始地址;建立各種大小的內(nèi)存頭信息鏈表,初始化為空;其中,每一種 大小的內(nèi)存塊對(duì)應(yīng)于一個(gè)內(nèi)存頭信息鏈表,每一個(gè)信息鏈表對(duì)應(yīng)于一個(gè)內(nèi)存 頭頭指針;步驟2:對(duì)用戶的內(nèi)存申請(qǐng),首先確定其需要的內(nèi)存塊大小,然后在步 驟l的內(nèi)存池中尋找是否有該大小的內(nèi)存塊處于空閑狀態(tài),如果有,則直接 申請(qǐng)使用,返回該內(nèi)存塊的地址,同時(shí)在該內(nèi)存塊對(duì)應(yīng)的內(nèi)存頭中設(shè)置使用 標(biāo)識(shí),同步更新空閑內(nèi)存頭指針;如果沒(méi)有,執(zhí)行下一步;步驟3,在ptAddrToUse有效的情況下,把ptAddfToUse +內(nèi)存頭大小 +內(nèi)存塊大小作為該大小的內(nèi)存塊使用,在內(nèi)存頭信息中記錄該內(nèi)存塊的位 置信息,并且加入該內(nèi)存塊大小的內(nèi)存頭信息鏈表中,遞增ptAddrToUse地 址,讓ptAddrToUse指向"ptAddrToUse +內(nèi)存頭大小+內(nèi)存塊大小,,,返 回未遞增前的ptAddrToUse地址作為用戶申請(qǐng)的內(nèi)存塊地址。進(jìn)一步地,還包括如下步驟步驟4:對(duì)用戶的內(nèi)存釋放,根據(jù)釋放地址,獲取其離內(nèi)存池中的偏移 位置,然后才艮據(jù)偏移位置得到內(nèi)存頭指針,最后將該內(nèi)存頭指針?lè)胖玫较鄳?yīng) 的空閑內(nèi)存塊鏈表尾部,同時(shí)設(shè)置內(nèi)存塊的使用標(biāo)志;步驟5:在系統(tǒng)中止運(yùn)行時(shí),釋放步驟l分配的內(nèi)存池。進(jìn)一步地,在所述步驟l中,所述內(nèi)存頭信息進(jìn)一步還包括該內(nèi)存頭 指向的內(nèi)存塊地址、返回給用戶的虛擬地址、占用標(biāo)志、所屬內(nèi)存池、下一 個(gè)內(nèi)存頭信息指針。進(jìn)一步地,在所述步驟l中,所述內(nèi)存頭頭指針至少包括塊大小信息和該鏈表中第一個(gè)內(nèi)存頭的頭地址信息。進(jìn)一步地,在所述步驟2中,所述確定需要的內(nèi)存塊大小是指如果要 求用戶申請(qǐng)的內(nèi)存大小在2q" 2q這樣一個(gè)區(qū)間中,即q為一個(gè)確定的整數(shù), 滿足2"〈申請(qǐng)內(nèi)存大小<=2q,則需要的內(nèi)存塊大小為2q。本發(fā)明盡可能地推遲了內(nèi)存池對(duì)特定大小的內(nèi)存塊的初始化, 一直到第 一次使用才進(jìn)行初始化,而且這時(shí)候如果該大小的內(nèi)存塊已經(jīng)有被用戶釋放 (放到空閑隊(duì)列中)的就不再進(jìn)行初始化,而得到"重新"利用,從而最大 程度地保證了內(nèi)存池中有隨時(shí)可以被使用的"空閑"的內(nèi)存,那些不可能使 用的內(nèi)存塊就不存在了 (不進(jìn)行初始化,其不占用內(nèi)存資源),不僅最大程 度的滿足了所需大小的內(nèi)存塊的需求,而且還有效緩解和避免了內(nèi)存浪費(fèi)和 內(nèi)存申請(qǐng)失敗的情況。附閨說(shuō)明
圖1為通用的內(nèi)存池管理方案示意圖。圖2為本發(fā)明內(nèi)存申請(qǐng)的實(shí)現(xiàn)示意圖。圖3為內(nèi)存頭鏈表示意圖。圖4為本發(fā)明的內(nèi)存申請(qǐng)的實(shí)現(xiàn)流程示意圖。圖5為本發(fā)明的內(nèi)存釋放示意圖。
具體實(shí)施方式
下面結(jié)合附圖對(duì)本發(fā)明進(jìn)行詳細(xì)描述。以下為 一個(gè)本發(fā)明實(shí)際應(yīng)用的具體實(shí)例,假設(shè)各內(nèi)存塊大小采用通常使 用的2'字節(jié)大小、22字節(jié)大小...2"字節(jié)大小(n為任意整數(shù))。要完成這種提高內(nèi)存池利用率的目的,本實(shí)例需要如下的步驟(以嵌入 式實(shí)時(shí)操作系統(tǒng)為舉例)步驟1:根據(jù)嵌入式軟件系統(tǒng)內(nèi)存的分配要求,在內(nèi)存資源中分配一個(gè) 大內(nèi)存池,專(zhuān)供用戶申請(qǐng)(釋放)內(nèi)存用。比如在VxWorks操作系統(tǒng)中, User Reserved (等于sysPhsMemTop( ) - sysMemTop())的內(nèi)存是用戶保留區(qū)域,就可以分配作為總的內(nèi)存池使用。其分配使用操作系統(tǒng)本身提供的動(dòng)態(tài)內(nèi)存分配函數(shù)如malloc來(lái)進(jìn)行分配。建立內(nèi)存頭信息鏈表,其內(nèi)存頭 信息需要包括如下基本信息typedef struct tagUBHeadBYTE *pAddr;/*該內(nèi)存頭指向的內(nèi)存塊地址*/BYTE IsUsed;/*使用標(biāo)志(避免重復(fù)釋放)*/BYTE Poollndex;/*所屬內(nèi)存池VOSSPNO ProcNo; /*申請(qǐng)的進(jìn)程號(hào)*/ T一UBHead *ptNext; /*指向下一個(gè)內(nèi)存頭信息*/ }T—UBHead;內(nèi)存頭信息鏈表初始化為空,如圖3所示。因?yàn)橛脩粼趦?nèi)存申請(qǐng)前并不 存在內(nèi)存頭,所以"內(nèi)存頭信息鏈表初始化為空,,表示沒(méi)有任何已經(jīng)分配好 的內(nèi)存塊,只是作為一種標(biāo)志。設(shè)置一個(gè)指針變量ptAddrToUse,用以指示該內(nèi)存池中可以用以分配內(nèi) 存塊的位置地址,其初始化地址為內(nèi)存池起始地址,如圖2所示。每一種大小的內(nèi)存塊對(duì)應(yīng)于一個(gè)內(nèi)存頭信息鏈表,每一個(gè)信息鏈表對(duì)應(yīng) 于一個(gè)內(nèi)存頭頭指針(圖3),內(nèi)存頭和相應(yīng)內(nèi)存塊在內(nèi)存池中連續(xù)設(shè)置, 內(nèi)存頭大小固定,而內(nèi)存頭頭指針是設(shè)置在另一內(nèi)存區(qū)域。內(nèi)存頭頭指針至 少包括有塊大小信息、該鏈表中第一個(gè)內(nèi)存頭的頭地址信息。其他信息,比 如調(diào)試信息等不是必須的。步驟2:對(duì)于內(nèi)存申請(qǐng),假如用戶申請(qǐng)Ubsize字節(jié)大小的內(nèi)存,尋找滿 足2^^Ubsize《2m條件的m值(m為整數(shù)),則用戶申請(qǐng)的內(nèi)存需要大小 由2m的內(nèi)存塊來(lái)提供使用。查找大小為2""的內(nèi)存頭鏈表。內(nèi)存申請(qǐng)流程如 圖4所示,具體是步驟2-l:如果大小為2""的內(nèi)存頭鏈表中存在空閑的內(nèi)存塊,則將該 空閑內(nèi)存頭中指向的地址返回給用戶,同時(shí)在該內(nèi)存塊對(duì)應(yīng)的內(nèi)存頭中設(shè)置使用標(biāo)識(shí),同步更新空閑內(nèi)存頭指針,即將空閑內(nèi)存塊指針移到鏈表下一個(gè) 內(nèi)存塊處。步驟2-2:如果大小為2m的內(nèi)存頭鏈表中不存在空閑的內(nèi)存塊或者鏈 表為空,則返回給用戶的是當(dāng)前的ptAddrToUse,表明(ptAddrToUse +內(nèi) 存頭大小+內(nèi)存塊大小即2m)這段內(nèi)存將被初始化為2m大小的內(nèi)存塊, 所以需要在內(nèi)存頭信息中記錄該內(nèi)存塊的位置信息,并且加入該內(nèi)存塊大小 的內(nèi)存塊頭信息鏈表中,同時(shí)需要讓ptAddrToUse指向(ptAddrToUse +內(nèi) 存頭大小+內(nèi)存塊大小即2"1)地址。如果ptAddrToUse無(wú)效,表明嵌入式軟件系統(tǒng)內(nèi)存的分配不能滿足系統(tǒng) 需要,可以以警告或是異常形式返回。步驟3:對(duì)用戶的內(nèi)存釋放,根據(jù)釋放地址,獲取其在內(nèi)存池中的偏移 位置,然后根據(jù)偏移位置得到內(nèi)存頭指針,最后將該內(nèi)存頭指針?lè)胖玫较鄳?yīng) 大小的空閑內(nèi)存塊鏈表尾部,同時(shí)設(shè)置內(nèi)存塊的使用標(biāo)志。如圖5所示。步驟4:在該嵌入式軟件模塊或系統(tǒng)中止運(yùn)行時(shí),釋放(對(duì)應(yīng)于步驟l 的malloc,采用free進(jìn)行釋放)步驟1分配的內(nèi)存池,釋放內(nèi)存頭信息鏈表, 設(shè)置指針變量ptAddrToUse為空??梢?jiàn),上述實(shí)例中避免了程序中不需要使用的內(nèi)存塊的初始化和占位, 最大程度的滿足了系統(tǒng)對(duì)某種大小內(nèi)存塊的使用需求,有效避免了小內(nèi)存塊煩瑣,提高了內(nèi)存池的利用率。所以該內(nèi)存池管理方法可以為用戶有效減少 內(nèi)存資源成本,尤其是在嵌入式軟件領(lǐng)域有更大的推廣價(jià)值和實(shí)用價(jià)值。
權(quán)利要求
1. 一種提高內(nèi)存池利用率的方法,其特征在于,包括如下步驟步驟1在內(nèi)存資源中分配一個(gè)大內(nèi)存池,用于用戶申請(qǐng)或釋放內(nèi)存;設(shè)置一個(gè)指針變量ptAddrToUse,用于指示該內(nèi)存池中可以用以分配內(nèi)存塊的起始地址;建立各種大小的內(nèi)存頭信息鏈表,初始化為空;其中,每一種大小的內(nèi)存塊對(duì)應(yīng)于一個(gè)內(nèi)存頭信息鏈表,每一個(gè)信息鏈表對(duì)應(yīng)于一個(gè)內(nèi)存頭頭指針;步驟2對(duì)用戶的內(nèi)存申請(qǐng),首先確定其需要的內(nèi)存塊大小,然后在步驟1的內(nèi)存池中尋找是否有該大小的內(nèi)存塊處于空閑狀態(tài),如果有,則直接申請(qǐng)使用,返回該內(nèi)存塊的地址,同時(shí)在該內(nèi)存塊對(duì)應(yīng)的內(nèi)存頭中設(shè)置使用標(biāo)識(shí),同步更新空閑內(nèi)存頭指針;如果沒(méi)有,執(zhí)行下一步;步驟3,在ptAddrToUse有效的情況下,把ptAddrToUse+內(nèi)存頭大小+內(nèi)存塊大小作為該大小的內(nèi)存塊使用,在內(nèi)存頭信息中記錄該內(nèi)存塊的位置信息,并且加入該內(nèi)存塊大小的內(nèi)存頭信息鏈表中,遞增ptAddrToUse地址,讓ptAddrToUse指向“ptAddrToUse+內(nèi)存頭大小+內(nèi)存塊大小”,返回未遞增前的ptAddrToUse地址作為用戶申請(qǐng)的內(nèi)存塊地址。
2、 根據(jù)權(quán)利要求1所述的一種提高內(nèi)存池利用率的方法,其特征在于, 還包括如下步驟步驟4:對(duì)用戶的內(nèi)存釋放,根據(jù)釋放地址,獲取其離內(nèi)存池中的偏移 位置,然后根據(jù)偏移位置得到內(nèi)存頭指針,最后將該內(nèi)存頭指針?lè)胖玫较鄳?yīng) 的空閑內(nèi)存塊鏈表尾部,同時(shí)設(shè)置內(nèi)存塊的使用標(biāo)志;步驟5:在系統(tǒng)中止運(yùn)行時(shí),釋放步驟l分配的內(nèi)存池。
3、 根據(jù)權(quán)利要求2所述的一種提高內(nèi)存池利用率的方法,其特征在于, 在所述步驟l中,所述內(nèi)存頭信息進(jìn)一步還包括該內(nèi)存頭指向的內(nèi)存塊地 址、返回給用戶的虛擬地址、占用標(biāo)志、所屬內(nèi)存池、下一個(gè)內(nèi)存頭信息指 針。
4、 根據(jù)權(quán)利要求3所述的一種提高內(nèi)存池利用率的方法,其特征在于, 在所述步驟l中,所述內(nèi)存頭頭指針至少包括塊大小信息和該鏈表中第一個(gè)內(nèi)存頭的頭地址信息。
5、 根據(jù)權(quán)利要求1所述的一種提高內(nèi)存池利用率的方法,其特征在于, 其中,在所述步驟2中,所述確定需要的內(nèi)存塊大小是指如果要求用戶申請(qǐng)的內(nèi)存大小在2q" 2q這樣一個(gè)區(qū)間中,即q為一個(gè)確定的整數(shù),滿足2q"<申請(qǐng)內(nèi)存大小<=2q,則需要的內(nèi)存塊大小為2q。
6、 根據(jù)權(quán)利要求1至5任一所述的一種提高內(nèi)存池利用率的方法,其 特征在于,可應(yīng)用于嵌入式實(shí)時(shí)操作系統(tǒng)。
全文摘要
本發(fā)明公開(kāi)了一種提高內(nèi)存池利用率的方法,該方法包括如下步驟步驟1在內(nèi)存資源中分配一個(gè)大內(nèi)存池,用于用戶申請(qǐng)或釋放內(nèi)存;設(shè)置一個(gè)指針變量ptAddrToUse,用于指示該內(nèi)存池中可以用以分配內(nèi)存塊的起始地址;建立各種大小的內(nèi)存頭信息鏈表,初始化為空;步驟2對(duì)用戶的內(nèi)存申請(qǐng),首先確定其需要的內(nèi)存塊大小,然后在步驟1的內(nèi)存池中尋找是否有該大小的內(nèi)存塊處于空閑狀態(tài);步驟3在ptAddrToUse有效的情況下,把ptAddrToUse+內(nèi)存頭大小+內(nèi)存塊大小作為該大小的內(nèi)存塊使用。本發(fā)明不僅最大程度的滿足了所需大小的內(nèi)存塊的需求,而且還有效緩解和避免了內(nèi)存浪費(fèi)和內(nèi)存申請(qǐng)失敗的情況。
文檔編號(hào)G06F12/06GK101266575SQ20071000567
公開(kāi)日2008年9月17日 申請(qǐng)日期2007年3月13日 優(yōu)先權(quán)日2007年3月13日
發(fā)明者徐立鋒, 王澤民 申請(qǐng)人:中興通訊股份有限公司