專利名稱:一種嵌入式操作系統(tǒng)的內存池分配方法
技術領域:
本發(fā)明涉及嵌入式實時操作系統(tǒng)領域,特別是涉及在嵌入式系統(tǒng)中,使用事先分配的內存池對應用申請的大小不確定的內存進行管理的實現方法。
背景技術:
隨著嵌入式實時系統(tǒng)在各個領域的廣泛應用,嵌入式軟件的開發(fā)也受到越來越多的矚目。在滿足系統(tǒng)實時性要求的前提下,如何提高內存分配的快速性、可靠性、高效性,是嵌入式軟件系統(tǒng)需要重點研究的一個課題。內存分配的快速性從嵌入式系統(tǒng)對實時性的要求出發(fā),要求內存在分配過程中盡可能的快,因此在嵌入式系統(tǒng)中,不可能采用通用操作系統(tǒng)中復雜而繁瑣的內存分配策略,一般都采用簡單、快速的內存分配方案;內存分配的可靠性則要求內存分配的請求必須得到滿足,如果分配失敗的話可能會帶來災難性的后果;而內存分配的高效性,則要求內存分配盡可能地少浪費。
目前,在嵌入式軟件開發(fā)中,特別是在諸如電信、信息家電這些行業(yè),由于對內存的申請和釋放比較頻繁,一般采用的內存分配方法是使用內存分塊管理的內存池方式。在開源的嵌入式實時操作系統(tǒng)μCOS-II中也采用了該種內存分配方式。它的技術方案如圖1所示,其中a表示各個內存頭信息,m、n、f均為任意整數。相同大小的內存塊由實箭頭構成一個鏈表。
為了避免由于內存頻繁申請和釋放而導致內存碎片,通用的內存池管理方式首先配置各種大小的內存塊的數量,比如21字節(jié)大小的內存塊m個,22字節(jié)大小的內存塊n個,以此類推,2n字節(jié)大小的內存塊f個(其中m、n、f均為任意整數),一般為了保證內存分配的可靠性,各種內存塊大小保持一個較大的上限值,同時在內存頭中保存每個內存塊的信息。然后在空閑內存中分配一個大內存,專門用于滿足用戶的內存申請需求,該內存池大小為各種大小的內存塊大小的總和,即(21×m+22×n+…+2n×f+所有內存頭大小)的值。
在進行內存申請時,根據申請內存的大小在相應的內存池中尋找滿足大小需要的內存塊,如果用戶申請的內存是在2q-1~2q這樣一個區(qū)間中(q為一個確定的整數,滿足2q-1<申請內存大小<=2q),則取一個空閑的2q大小的內存塊分配給應用;內存釋放是根據內存塊的的指針找到相應的頭,再將其標記為自由內存并歸還給相應的緩沖池的過程。
在該內存池分配方法中,不可能把內存塊大小差距配置得很小、很均勻,比如內存塊大小1,2,4,6...2n,因為內存塊大小差距太小,需要保存的內存頭指針就多,導致內存的申請和釋放的查找耗時劇增,直接影響內存分配的快速性;同時,諸如內存頭大小這樣的額外的開銷也大大增加。所以,一般各內存塊是采取諸如2n這樣的分配方式的。
這種通用的內存池管理方法針對頻繁申請和釋放的內存,可以高效,可靠的滿足應用需要,同時也可以較好的避免內存碎片的問題。因此在目前的嵌入式軟件開發(fā)中,有很大范圍的應用。
但是,這種通用的內存池管理方式對內存的使用有時是有比較大的浪費的。因為,對于用戶申請的內存UB,其對應的內存塊是在2n-1<=UB<2n這樣一個區(qū)間中,但是經過內存池選擇出的內存塊大小則是2n(必須要不小于2n,否則會導致內存申請失敗),這樣就存在(2n-UB)大小的空間浪費,特別是UB為2n-1+1的時候尤為明顯,而且n值愈大,內存耗費愈大;如果存在一定數量的用戶申請的內存,其大小落在靠近2n-1且大于2n-1附近的話,這種浪費就可能對嵌入式產品產生致命影響了,因為一方面,嵌入式系統(tǒng)對成本的要求使得內存在其中只是一種很有限的資源;而另一方面,即使不考慮成本的因素,系統(tǒng)有限的空間和有限的板面積決定了可配置的內存容量是很有限的。
如何揚長避短,既保持通用內存池管理的高效性等優(yōu)點,又避免其可能存在的內存浪費是更好利用內存池管理方式的關鍵。
發(fā)明內容
本發(fā)明所要解決的技術問題是提供一種嵌入式操作系統(tǒng)的內存池分配方法,解決現有技術的內存浪費的問題。
為達到上述目的,本發(fā)明提供了一種嵌入式操作系統(tǒng)的內存池分配方法,其特點在于,包括如下步驟步驟一,根據用戶可能使用到的各種內存塊的大小和數量以及對應的內存頭的大小,在內存資源中分配一個由所述內存塊和內存頭構成的內存池;步驟二,對所述內存池進行初始化,確定各種大小的內存塊的起始地址;步驟三,對于內存申請,如果滿足該內存申請的最小的單一內存塊存在超過閥值的浪費,則通過組合不同大小的多個內存塊來滿足該內存申請。
上述的方法,其特點在于,所述步驟二中,確定所述起始地址采用如下規(guī)則一個最大的內存塊的結束地址是一個次大的內存塊的起始地址,依次類推,最后是一個最小的內存塊的結束地址,從而內存塊按從大到小的次序構成一個循環(huán);一個循環(huán)結束,再重復下一個循環(huán)的配置,同時,在內存頭中記錄各內存塊的起止地址和是否空閑的信息。
上述的方法,其特點在于,在所述步驟三中,所述存在超過閥值的浪費為所述單一內存塊與緊跟所述單一內存塊的次大內存塊的平均值大于所述內存申請。
上述的方法,其特點在于,在所述步驟三中,通過組合緊跟在所述單一內存塊之后的兩個內存塊來分配給所述內存申請。
上述的方法,其特點在于,所述步驟三進一步包括步驟A,判斷所述內存申請是否小于所述單一內存塊與所述次大內存塊的平均值,是則執(zhí)行步驟B,否則執(zhí)行步驟D;步驟B,判斷緊跟在所述單一內存塊之后的兩個內存塊之和是否大于所述內存申請,是則執(zhí)行步驟C,否則執(zhí)行步驟D;步驟C,把所述兩個內存塊分配給所述內存申請,內存分配結束;步驟D,直接把所述單一內存塊分配給所述內存申請,內存分配結束。
上述的方法,其特點在于,還包括步驟四,在所述內存申請的應用結束后,對所述內存申請的內存塊進行釋放。
上述的方法,其特點在于,在所述步驟四中,如果被釋放的內存為多個內存塊的組合,則拆開所述組合的所述多個內存塊,進行各內存塊的單獨釋放。
上述的方法,其特點在于,還包括所述內存塊按照內存地址的遞增構成一個單向鏈表一,所有相同大小的未被分配的空閑內存塊又構成一個單向鏈表二,并在內存塊的內存頭中的相應位置標明該內存塊在所述鏈表一和鏈表二中的順序號。
上述的方法,其特點在于,還包括在所述內存池的管理結構中記錄內存塊大小、數量以及有無后繼的內存池的索引,在內存頭中記錄對應內存塊的起始地址、占用標志以及有無比其大小還小的后繼內存塊標志。
本發(fā)明的技術效果在于本發(fā)明提供的嵌入式軟件的內存池分配的實現方法,不僅能夠充分利用目前通用內存池高效、可靠、不產生內存碎片等優(yōu)點,還可以有效的降低、緩解、甚至解決通用內存池可能存在的內存浪費,使其更好的滿足嵌入式軟件開發(fā)對內存分配的要求。本發(fā)明可以很大程度的減小和緩解通用內存池管理中存在的內存資源浪費的問題,同時,也保持了通用內存池管理的高效性和可靠性。
圖1為通用的內存池管理方案示意圖;圖2為本發(fā)明中的一個內存池中內存頭和內存塊的關系示意圖;圖3為本發(fā)明中的內存池初始化示意圖;圖4為本發(fā)明的整個內存池管理管理方法的實現流程示意圖;圖5為本發(fā)明中的內存浪費可以接受時的內存分配示意圖;圖6為本發(fā)明中的內存浪費嚴重時的內存分配示意圖;圖7為本發(fā)明中的內存塊釋放示意圖。
具體實施例方式
下面結合附圖對本發(fā)明進行詳細描述。
本發(fā)明提供了一種新的嵌入式軟件的內存池管理的實現方法,這種方法不僅能夠充分利用目前通用內存池高效、可靠、不產生內存碎片等優(yōu)點,還可以有效的降低、緩解、甚至解決通用內存池可能存在的內存浪費,使其更好的滿足嵌入式軟件開發(fā)對內存分配的要求。
本發(fā)明的嵌入式操作系統(tǒng)的內存池管理方法,包括如下步驟步驟1對用戶可能使用的各種內存塊大小和數量進行配置,然后根據用戶使用的內存塊大小以及內存頭等附加信息大小的總和在嵌入式軟件的內存資源中分配一個內存池,專供用戶申請(釋放)內存用;步驟2對步驟1的內存池進行初始化,即確定各種大小的內存塊的起始地址。分配各種大小的內存起始地址的規(guī)則是,一個最大的內存塊的結束地址是一個次大的內存塊的起始地址,依次類推,最后是一個最小的內存塊的結束地址;同理,一個循環(huán)結束,再重復如此的配置。同時,在內存頭中記錄各內存塊的起止地址、是否空閑等情況。
步驟3對內存申請,比較用戶申請的內存大小和滿足條件的最小的內存塊大小,如果內存浪費比較嚴重,則使用比滿足條件的內存塊小的兩個地址連續(xù)且大小遞減的內存塊來分配給用戶使用,同時設置內存塊使用標志;只有在比滿足條件的最小內存塊小的兩個地址連續(xù)且大小遞減的內存塊無法提供用戶申請的內存時,才使用滿足條件的內存塊來提供給用戶使用。
步驟4對內存釋放,放置內存塊到相應的空閑內存塊后,同時設置內存塊的使用標志。
步驟5在該嵌入式軟件模塊或系統(tǒng)中止運行時,釋放步驟1分配的內存池。
其中,步驟2中各種大小的內存塊的數目是允許不相同的,因而可能出現這種情況,比如最大的內存塊結束地址是第三大的內存塊的起始地址,但對用戶的內存分配過程不會產生影響。
步驟3中,對內存浪費是否嚴重的判斷準則相對比較靈活,但是考慮到便捷性和使用的高效性,使用連續(xù)大小的兩個內存塊(此時用戶申請的內存塊大小大于其中小內存塊而小于其中大內存塊)的中間點來進行判斷,用戶申請的內存塊落在小內存塊和該中間點區(qū)間時,認定內存浪費嚴重;而落在該中間點和大內存塊區(qū)間時,認定為內存浪費可以接收。
步驟4中,如果是連續(xù)的兩個內存塊的釋放,對每個內存塊單獨釋放,即把每個內存塊放入其相應的空閑內存塊后。
以下為一個本發(fā)明實際應用的具體實例,假設配置的內存塊情況是21字節(jié)大小的內存塊n個,22字節(jié)大小的內存塊n+1個,依次類推,2n字節(jié)大小的內存塊n+n個(n為任意整數)。
要完基于如上配置的嵌入式內存池管理的目的,本實例需要如下的步驟
步驟1)計算所需要的內存池大小。內存池大小由三部分組成,一是內存塊總大小,即(21×n+22×(n+1)+…+2n×(n+n)的和;二是內存頭大小總和,內存頭需要保存返回給用戶的內存地址、占用標志、所屬內存池、其后內存塊占用標志、內存塊在在相同大小的內存塊組成的內存池中的索引順序號(seq1)、內存塊在按地址順序遞變的內存池中的索引順序號(seq2)以及一些調試信息。三是各種大小的內存池的管理結構的大小之和(一種大小的內存池有一個管理結構),該內存池的管理結構需要記錄諸如該內存池內存塊的大小、數量、單獨的內存塊在內存池的第一個空閑的索引、單獨的內存塊在內存池的最近一個釋放塊的索引、連續(xù)的內存塊在內存池的第一個空閑的索引以及連續(xù)的內存塊在內存池的最近一個釋放塊的索引等信息。然后根據所需要的內存池大小進行內存分配。內存池中內存頭和內存塊的具體關系可參考圖2。
步驟2)進行內存池初始化。分配內存頭、內存池管理結構所占有的內存。依次連續(xù)分配一個2n,2n-1,…,21字節(jié)大小的內存塊,同理在第一個循環(huán)分配完后,進行下一個循環(huán)分配,直至所有的內存塊起始地址分配結束,這樣按照內存地址的遞增構成了一個單向鏈表一,同時在內存池管理結構中記錄該池中內存塊大小、數量,以及有無后繼的內存池的索引,在內存頭中記錄該內存塊的起始地址、占用標志,以及有無比其大小還小的后繼內存塊標志等。所有相同大小的未被分配的空閑內存塊又構成一個單向鏈表二,以便于分配時快速查找、索引。兩個單向鏈表要使用內存頭中的seq1和seq2來標明在對方鏈表中的順序號,以便于鏈表對特定節(jié)點的增加和刪除,避免對整個鏈表的遍歷,圖3為本發(fā)明中的內存池初始化示意圖,如圖3所示,其中虛箭頭表示相同大小的內存塊構成一個單向鏈表;實箭頭表示按照內存地址的遞增構成的一個單向鏈表。
步驟3)對于內存申請,假如用戶申請Ubsize字節(jié)大小的內存,存在滿足2n-m-1<Ubsize<=2n-m條件內存塊(m為小于n的整數)。如果Ubsize大小在2n-m-1~(2n-m-1+(2n-m-2n-m-1)/2)區(qū)間中,則認為存在嚴重的內存浪費(此時,浪費內存大于(2n-m-2n-m-1)/2),如果在(2n-m-1+(2n-m-2n-m-1)/2)~2n-m區(qū)間,則認為內存浪費是可以接受的(此時,浪費內存小于(2n-m-2n-m-1)/2)。
步驟3-1如果對內存申請而分配的內存塊被認為內存浪費是可以接受的。通過單獨的內存塊索引頭尋找空閑內存塊,進行內存分配,同時設置占有和無后繼內存塊標志;然后根據其內存頭中的seq2索引號對單向鏈表1中的seq2映射的節(jié)點進行刪除。如圖4所示,為本發(fā)明的整個內存池管理管理方法的實現流程示意圖,具體包括如下步驟步驟401,根據用戶對內存的使用需求分配一個內存池;步驟402,按規(guī)則確定各種大小的內存塊在內存池的起始地址;步驟403,建立內存塊按地址遞增的鏈表1和內存塊按同等大小依次建立的內存池鏈表2;步驟404,用戶調用接口類型,如為內存申請則執(zhí)行步驟405,如為內存釋放則執(zhí)行步驟406;步驟405,進行內存申請;步驟406,進行內存釋放。
步驟3-2如果對內存申請而分配的內存塊被認為內存浪費是不可以接受的。通過連續(xù)的內存塊索引頭尋找空閑內存塊,并查找其地址后的地址連續(xù)的兩個內存塊(UB1和UB2)且UB1大于UB2,如果(UB1+UB2)大小滿足用戶需要,對其進行內存分配,同時設置占有和無后繼內存塊標志;然后分別根據其內存頭中的seq1索引號對單向鏈表2中的seq1映射的節(jié)點進行刪除。如果整個單向鏈表1中不存在這樣的地址連續(xù)兩個內存塊,執(zhí)行步驟3-1。圖5為本發(fā)明中的內存浪費可以接受時的內存分配示意圖,如圖5所示,具體包括步驟501,內存池中有滿足申請的內存塊;步驟502,判斷內存浪費是否超過閥值,是則轉到內存嚴重浪費的分配流程60,否則執(zhí)行步驟503;步驟503,把該內存塊從內存池鏈表中脫鏈;步驟504,把該滿足申請的內存塊從按地址構建的鏈表中脫鏈。
圖6為本發(fā)明中的內存浪費嚴重時的內存分配示意圖,如圖所是包括如下步驟步驟60,承接圖5中的步驟502的判斷條件,即內存浪費超過閥值;
步驟601,判斷在該滿足申請的內存塊地址后方是否存兩個容量之和滿足該申請需求的內存塊,是則執(zhí)行步驟602,否則執(zhí)行步驟604;步驟602,把所述兩個內存塊從按地址構建的鏈表中脫鏈;步驟603,把所述兩個內存塊從內存池鏈表中脫鏈,并把所述兩個內存塊分配給申請,結束流程;步驟604,把該滿足申請的單一內存塊分配給申請,結束流程。
(6)步驟4-1對于內存釋放,如果是步驟3-1中申請的內存塊的釋放,將其加入單向鏈表2中的末尾;然后根據其內存頭中的seq2索引號對單向鏈表1中的seq2映射的節(jié)點(需要查看內存地址大小是否滿足遞增條件)進行鏈表增加,同時設置占有和無后繼內存塊標志。圖7為本發(fā)明中的內存塊釋放示意圖,如圖,內存塊的釋放具體包括如下步驟步驟701,判斷釋放的內存塊的大小和地址是否為兩個內存塊的組合,是則執(zhí)行步驟702,某則執(zhí)行步驟704;步驟702,分別把這兩塊內存塊放入按地址構建的鏈表中;步驟703,分別把這兩塊內存塊放入內存池鏈表,結束釋放;步驟704,把該單一內存塊放入內存池的鏈表中;步驟705,把該單一內存塊放入按地址構建的鏈表中,結束釋放。
步驟4-2如果是步驟3-2中申請的內存塊的釋放,對每一個內存塊單獨執(zhí)行步驟3-1進行釋放。
步驟5)如果系統(tǒng)停止運行,對步驟1)中申請的內存池進行釋放。
可見,上述實例中一般可以減少(2n-m-2n-m-1)/2)的內存浪費(最多可以減少2n-m-2n-m-1-1),有效降低、緩解了通用內存池管理中存在的浪費情況;同時,采用了在內存頭中建立相應索引順序號的方法,避免了對內存塊的遍歷,保證了內存分配和釋放的高效性和快速性;由于整個內存池的初始化、鏈表的建立一般都是在系統(tǒng)初始化階段進行,不會對程序運行產生附加的額外影響,保證了該內存池管理方法的運行平穩(wěn)性。所以該內存池管理方法可以為用戶有效減少內存資源成本,在嵌入式軟件領域有很大的推廣價值和實用價值。
本領域的技術人員可根據發(fā)明內容部分的技術方案構成多個實施例,比如,利用緊跟在滿足內存申請的最小單一內存塊之后的三個、四個或五個內存塊分配給所述內存申請,或者利用其他規(guī)則任選比所述單一內存塊小的多個內存塊,雖然其實現起來相對于以上實施例較為復雜并且效果較差,但仍在本發(fā)明的范圍之內,本領域的技術人員只需對以上實施例作出較小的變通即可實現。
因此以上所述僅為本發(fā)明的較佳實施例,并非用來限定本發(fā)明的實施范圍;凡是依本發(fā)明所作的等效變化與修改,都被本發(fā)明的專利范圍所涵蓋。
權利要求
1.一種嵌入式操作系統(tǒng)的內存池分配方法,其特征在于,包括如下步驟步驟一,根據用戶可能使用到的各種內存塊的大小和數量以及對應的內存頭的大小,在內存資源中分配一個由所述內存塊和內存頭構成的內存池;步驟二,對所述內存池進行初始化,確定各種大小的內存塊的起始地址;步驟三,對于內存申請,如果滿足該內存申請的最小的單一內存塊存在超過閥值的浪費,則通過組合不同大小的多個內存塊來滿足該內存申請。
2.根據權利要求1所述的方法,其特征在于,所述步驟二中,確定所述起始地址采用如下規(guī)則一個最大的內存塊的結束地址是一個次大的內存塊的起始地址,依次類推,最后是一個最小的內存塊的結束地址,從而內存塊按從大到小的次序構成一個循環(huán);一個循環(huán)結束,再重復下一個循環(huán)的配置,同時,在內存頭中記錄各內存塊的起止地址和是否空閑的信息。
3.根據權利要求2所述的方法,其特征在于,在所述步驟三中,所述存在超過閥值的浪費為所述單一內存塊與緊跟所述單一內存塊的次大內存塊的平均值大于所述內存申請。
4.根據權利要求3所述的方法,其特征在于,在所述步驟三中,通過組合緊跟在所述單一內存塊之后的兩個內存塊來分配給所述內存申請。
5.根據權利要求4所述的方法,其特征在于,所述步驟三進一步包括步驟A,判斷所述內存申請是否小于所述單一內存塊與所述次大內存塊的平均值,是則執(zhí)行步驟B,否則執(zhí)行步驟D;步驟B,判斷緊跟在所述單一內存塊之后的兩個內存塊之和是否大于所述內存申請,是則執(zhí)行步驟C,否則執(zhí)行步驟D;步驟C,把所述兩個內存塊分配給所述內存申請,內存分配結束;步驟D,直接把所述單一內存塊分配給所述內存申請,內存分配結束。
6.根據權利要求1所述的方法,其特征在于,還包括步驟四,在所述內存申請的應用結束后,對所述內存申請的內存塊進行釋放。
7.根據權利要求6所述的方法,其特征在于,在所述步驟四中,如果被釋放的內存為多個內存塊的組合,則拆開所述組合的所述多個內存塊,進行各內存塊的單獨釋放。
8.根據權利要求2所述的方法,其特征在于,還包括所述內存塊按照內存地址的遞增構成一個單向鏈表一,所有相同大小的未被分配的空閑內存塊又構成一個單向鏈表二,并在內存塊的內存頭中的相應位置標明該內存塊在所述鏈表一和鏈表二中的順序號。
9.根據權利要求8所述的方法,其特征在于,還包括在所述內存池的管理結構中記錄內存塊大小、數量以及有無后繼的內存池的索引,在內存頭中記錄對應內存塊的起始地址、占用標志以及有無比其大小還小的后繼內存塊標志。
全文摘要
本發(fā)明公開了一種嵌入式操作系統(tǒng)的內存池分配方法,包括步驟一,根據用戶可能使用到的各種內存塊的大小和數量以及對應的內存頭的大小,在內存資源中分配一個由所述內存塊和內存頭構成的內存池;步驟二,對所述內存池進行初始化,確定各種大小的內存塊的起始地址;步驟三,對于內存申請,如果滿足該內存申請的最小的單一內存塊存在超過閥值的浪費,則通過組合不同大小的多個內存塊來滿足該內存申請。本發(fā)明可以很大程度的減小和緩解通用內存池管理中存在的內存資源浪費的問題,同時,也保持了通用內存池管理的高效性和可靠性。
文檔編號G06F9/46GK101093455SQ20061008936
公開日2007年12月26日 申請日期2006年6月21日 優(yōu)先權日2006年6月21日
發(fā)明者王澤民, 徐立峰, 曹剛 申請人:中興通訊股份有限公司