《LINUX實操:SylixOS 定長內存管理》要點:
本文介紹了LINUX實操:SylixOS 定長內存管理,希望對您有用。如果有疑問,可以聯系我們。
所謂定長內存,指的是用戶每次分配獲得的內存年夜小是相同的,即使用的是有確定長度的內存塊.同時,這些內存塊總的個數也是確定的,即整個內存總的年夜小也是確定的.這和通常理解的內存池的概念是一樣的.
使用定長內存管理的內存,有兩大長處:一是由于事先已經分配好了足夠的內存,可極大提高關鍵應用的穩定性;二是對于定長內存的管理通常有更為簡單的算法,分配/釋放的效率更高.在 SylixOS 中,將管理的一個定長內存稱作 PARTITION,即內存分區.
SylixOS可以通過API操作實現定長內存管理功效.
#include<SylixOS.h> LW_OBJECT_HANDLE? Lw_Partition_Create(CPCHAR? ? ? ? ? ? pcName, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PVOID? ? ? ? ? ? ? pvLowAddr, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ULONG? ? ? ? ? ? ? ulBlockCounter, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? size_t? ? ? ? ? ? stBlockByteSize, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ULONG? ? ? ? ? ? ? ulOption, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LW_OBJECT_ID? ? ? *pulId) |
函數Lw_Partition_Create 原型闡發:
1.此函數成功時返回一個內存分區句柄,失敗時返回LW_HANDLE_INVALID并設置差錯號;
2.參數pcName指定該內存分區的名稱,可以為LW_NULL(最年夜字長為32字節);
3.參數pvLowAddr為用戶定義的一片內存的低地址,即起始地址.該地址必需滿足一個CPU字長的對齊,如在32位系統中,該地址必需4字節對齊;
4.參數 ulBlockCounter 為該內存分區的定長內存塊數目;
5.參數 stBlockByteSize 為內存塊的大小,必需不小于一個指針的長度,在32位系統中為4字節;
6.參數ulOption為創立內存分區的選項,如表 2-1所示.
表 2-1? 內存分區創立選項
7.輸出參數 pulId 保留該內存分區的 ID,與返回值相同.可以為 LW_NULL.
?
注:驅動程序或內核模塊才能使用LW_OPTION_OBJECT_GLOBAL 選項,對應的LW_OPTION_OBJECT_LOCAL 選項用于應用程序.為了使應用程序有更好的兼容性,建議使用LW_OPTION_DEFAULT選項,該選項包括了 LW_OPTION_OBJECT_LOCAL 的屬性.
SylixOS的Lw_Partition_Create把已分配好的一塊大內存(pvLowAddr)通過一個PARTITION控制塊進行管理,PARTITION控制塊內容如法式清單 2-1所示.
法式清單2-1? PARTITION控制塊
/淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂* ? PARTITION 節制塊 淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂淫亂*/ typedefstruct { ? ? LW_LIST_MONO? ? ? ? PARTITION_monoResrcList;? ? ? ? ?/*? 余暇資源表? ? ? ? ? ? ?*/ ? ? UINT8? ? ? ? ? ? ? ? PARTITION_ucType;? ? ? ? ? ? ? ? /*? 類型標記? ? ? ? ? ? ? ?*/ ? ? PLW_LIST_MONO? ? ? ? PARTITION_pmonoFreeBlockList;? /*? 余暇內存塊表? ? ? ? ? ?*/ ? ? size_t? ? ? ? ? ? ? PARTITION_stBlockByteSize;? ? ? /*? 每一塊的年夜小? ? ? ? ? ?*/ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*? 必需大于 sizeof(PVOID)*/ ? ? ULONG? ? ? ? ? ? ? ? PARTITION_ulBlockCounter;? ? ? ? /*? 塊數目 ? ? ? ? ? ? ? ? */ ? ? ULONG? ? ? ? ? ? ? ? PARTITION_ulFreeBlockCounter;? ? /*? 余暇塊數量? ? ? ? ? ? ?*/ ? ? UINT16? ? ? ? ? ? ? PARTITION_usIndex;? ? ? ? ? ? ? ? /*? 緩沖區索引? ? ? ? ? ? */? ? ? CHAR? ? ? ? ? ? ? ? PARTITION_cPatitionName[LW_CFG_OBJECT_NAME_SIZE]; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*? 名字? ? ? ? ? ? ? ? ? */ ? ? LW_SPINLOCK_DEFINE? (PARTITION_slLock);? ? ? ? ? ? ?/*? 自旋鎖? ? ? ? ? ? ? ? */ } LW_CLASS_PARTITION; |
Lw_Partition_Create對特定內存管理好后,會返回一個LW_OBJECT_HANDLE句柄.之后用戶必要對這塊內存進行獲取、釋放和刪除等,都可以通過這個句柄進行操作.
PVOID? Lw_Partition_Get (LW_OBJECT_HANDLE? ulId) PVOID? Lw_Partition_Put (LW_OBJECT_HANDLE? ulId, PVOID? pvBlock) |
調用 Lw_Partition_Get 函數可以獲得一個內存分區的內存塊,其大小為創立內存分區時指定的大小,調用Lw_Partition_Put 函數將獲得的內存塊(Lw_Partition_Get 函數獲得)返回給內存分區.
注:如果pvBlock為 NULL,則設置差錯號為 ERROR_PARTITION_NULL.
ULONG? Lw_Partition_Delete (LW_OBJECT_HANDLE? *pulId) ULONG? Lw_Partition_DeleteEx (LW_OBJECT_HANDLE? *pulId, BOOL? bForce) |
如果一個內存分區中有內存塊還在被使用,則理論上不該該立刻被刪除.如果bForce為 LW_TRUE,則 Lw_Partition_DeleteEx 忽略該條件直接刪除該分區.通常情況下應用程序不該該使用該方式,這可能會導致內存錯誤.建議一般情況下使用 Lw_Partition_Delete 函數,它相當于下面調用,這樣避免釋放還在使用的內存.
Lw_Partition_DeleteEx(pulId, LW_FALSE); |
好比程序需要創建一個鏈表,可以使用定長內存管理.如程序清單 3-1所示.
法式清單 3-1? 法式代碼
#include<stdio.h> #include<SylixOS.h> ? typedefstruct my_element { ? ? INTiValue; } MY_ELEMENET; ? #define? ?ELEMENT_MAX (8) ? /* ?* 即當_G_pucMyElementPool 的地址不滿足布局體 MY_ELEMENT 的對齊需求時,在有些硬件上, ?* 拜訪成員變量 iValue 將產生多字節不對齊拜訪的錯誤(典型的硬件平臺如 ARM). * 應該將_G_pucMyElementPool 的類型定義為UINT8,即單字節拜訪,邏輯上它的起始地址可以是任? * 何對齊值. ?*/ MY_ELEMENET_G_pmyelement[ELEMENT_MAX]; LW_STACK? ? _G_pucMyElementPool[sizeof(MY_ELEMENET) * ELEMENT_MAX / ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?sizeof(LW_STACK)]; ? ? ? ?/*? 申請一段內存空間? ? */ LW_HANDLE? ?_G_hMyPartition;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*? 內存治理句柄 ? ? ? ? */? ? ? ? ? ? ? ? ? ? ? ? ? ? intmain(intargc, char *argv[]) { ? ? MY_ELEMENET *peleTable[ELEMENT_MAX] ? = { LW_NULL }; ? ? MY_ELEMENET *peleTmp? ? ? ? ? ? ? ? ? = NULL; ? ? ULONG? ? ? ? ulError; ? ? INT? ? ? ? ? i? ? ? ? ? ? ? ? ? ? ? ?= 0; ? ? ? _G_hMyPartition = Lw_Partition_Create("my_partition", _G_pucMyElementPool, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ELEMENT_MAX, sizeof(MY_ELEMENET), ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LW_OPTION_DEFAULT, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LW_NULL); ? ? if (_G_hMyPartition == LW_HANDLE_INVALID) { ? ? ? ? fprintf(stderr, "create partition failed.\n"); ? ? ? ? return (-1); ? ? } ? ? /* ? ? ?* 最多能夠得到多少個元素內存 ? ? ?*/ ? ? while (1) { ? ? ? ? peleTmp = (MY_ELEMENET *) Lw_Partition_Get(_G_hMyPartition); ? ? ? ? if (peleTmp != LW_NULL) { ? ? ? ? ? ? peleTable[i] = peleTmp; ? ? ? ? ? ? peleTmp->iValue = i; ? ? ? ? ? ? fprintf(stdout, "get element successfully, count = %d.\n", i); ? ? ? ? } else { ? ? ? ? ? ? fprintf(stderr, "get element failed, count = %d.\n", i); ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? i++; ? ? } ? ? /* ? ? ?* 在沒有全部回收元素內存的環境下刪除內存分區 ? ? ?*/ ulError = Lw_Partition_Delete(&_G_hMyPartition); /*無法刪除還有未收受接管所有內存*/ ? ? if (ulError != ERROR_NONE) { ? ? ? ? fprintf(stderr, "delete partition error.\n"); ? ? } else { ? ? ? ? return (0); ? ? } ? ? /* ? ? ?* 收受接管內存塊返回給內存分區 ? ? ?*/ ? ? for (i = 0; i < ELEMENT_MAX; i++) { ? ? ? ? peleTmp = peleTable[i]; ? ? ? ? if (peleTmp != LW_NULL) { ? ? ? ? ? ? fprintf(stdout, "element%d value = %d.\n", i, peleTmp->iValue); ? ? ? ? ? ? peleTmp = Lw_Partition_Put(_G_hMyPartition, peleTmp); ? ? ? ? ? ? if (peleTmp != LW_NULL) { ? ? ? ? ? ? ? ? fprintf(stderr, "element%d put failed.\n", i); ? ? ? ? ? ? } ? ? ? ? } else { ? ? ? ? ? ? break; ? ? ? ? } ? ? } ? ? /* ? ? ?* 全部收受接管元素內存后刪除內存分區 ? ? ?*/ ? ? ulError = Lw_Partition_Delete(&_G_hMyPartition); /*? ?可以刪除內存分區? ? ? ? ? */ ? ? if (ulError != ERROR_NONE) { ? ? ? ? fprintf(stderr, "delete partition error.\n"); ? ? ? ? return (-1); ? ? } else { ? ? ? ? fprintf(stderr, "delete partition successfully.\n"); ? ? } ? ? return (0); } |
內存分區不直接分配內存,它只是提供了一個管理內存的辦法.因此在創建內存分區時,需要指定需要管理的內存,該內存由使用的元素(即上面所述的內存塊)大小以及元素的最大個數決定.在程序清單 31中,創建了一個最大可以容納 8 個類型為MY_ELEMENT 對象的內存分區,然后通過獲取元素對象、使用元素對象以及刪除內存分區三方面展示了SylixOS 內存分區的使用.該程序運行后,結果如下所示:如圖 3-1所示.
圖 3-1? 程序運行成果
從運行結果可以看出,最大元素個數為8個,因此第9次獲取元素時會失敗.隨后使用Lw_Partition_Delete函數刪除內存分區,由于此時元素還未被回收,因此刪除失敗.當回收完全部的元素后,能力成功刪除.
本文永遠更新鏈接地址:
維易PHP培訓學院每天發布《LINUX實操:SylixOS 定長內存管理》等實戰技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養人才。