您好,登錄后才能下訂單哦!
本篇內容介紹了“內存池的實現方式”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
這篇文章主要介紹一下內存池的實現方式,這里介紹的是一種比較經典的內存池實現方式,就是鏈表法實現,具體原理如下:
1,首先內存池無非是提前申請一大塊內存片段,之后把這個片段上的指針分配給用戶,對于分配來說只要記住已經分配的偏移量即可,每次分配將指針后移申請的內存塊長度即可。
2,主要問題在于釋放內存,由于不確定用戶申請和釋放內存的順序,必須假定申請和釋放都在交疊進行,
對于內存池來說,釋放的空間必須要可以復用,否則內存池失去了意義;
但是先申請的內存區域可能先釋放,這樣將出現釋放的區域位于已分配區域中間的情形;如何索引這些釋放的內存片段是內存池要主要解決的問題;
見下圖:
未命名文件.jpg
圖中X區域先申請,當申請了Y區域之后,釋放了X區域,此時如何能夠復用X區域的內存,而不是只能使用Y區域之后的內存時要解決的問題;
內存池的鏈表法實現見第二幅圖,每個申請的區域前有一個固定長度的頭部,其中記錄了一些信息,最重要的是兩個指針,一個指向后面的內存塊頭部,另一個指向前面的內存塊頭部,并且末尾的內存塊和首部鏈接起來,構成一個雙向環形鏈表結構;
同時還有個標記位標志這塊內存有沒被使用;
當申請內存時,從鏈表首部開始遍歷找到第一個沒有使用的內存塊,判斷其大小是否滿足,如不滿足,繼續搜索;直到滿足條件,此時分2種情形:
1,可用內存塊大小和要申請的大小一樣,則直接標記為已使用,并返回即可
2,可用內存塊大于要申請的內存塊,則把可用內存區間分裂為2部分,前一部分標記為已使用,后一部分標記為未使用,并繼續保持它們的鏈表結構;
對于釋放內存,需要判斷是否前面和后面相鄰的內存塊有未使用,如果有,則需要合并,這一步至關重要,因為如果存在大量相鄰的標記未使用內存可能會導致無法分配一塊較大區域,
以上操作始終保持鏈表結構,就可以實現一個基礎內存池了;
實際上,這個實現思路來自于John Carmack在Quake3中的實現
但是我們可以稍微做一點優化(不過要犧牲一些額外的存儲空間)優化方法是,額外記錄兩個指針,以環形形式連接所有未使用的內存空間,這樣,查找的效率提高了,幾乎提升到了常數時間,
同時這個內存池還有一個缺陷就是長度固定,不過順著這個思路,我們可以在內存不夠時,新分配一塊大的區域,并且保持原來的鏈表結構即可,
下面附上代碼實現,見
https://github.com/wiltchamberian/MemoryPool
這里實現了兩個,第一個是參考Quake3 Carmack的實現
第二個SuperMemoryPool是改良后的實現,改良版實現的速度要提高了一些,支持動態內存
“內存池的實現方式”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。