Abstract:Static memory is essentially a static array. The size of the block in the static memory pool is set during initialization. After initialization, the size of the block cannot be changed. The static memory pool consists of a control block and several memory blocks of the same size. The control block is located in the memory pool header and is used for memory block management. Memory blocks are applied and freed at block size granularity.

This article is from the Huawei cloud community “HongMeng light kernel M kernel source analysis series eight Static Memory”, the original author: zhushy.

The memory management module manages the memory resources of the system. It is one of the core modules of the operating system, including the initialization, allocation and release of the memory.

During the operation of the system, the memory management module manages the use of memory by users and OS through the application/release of memory, so as to optimize the utilization and efficiency of memory and solve the memory fragmentation problem of the system to the greatest extent.

The memory management of Hongmeng light kernel is divided into static memory management and dynamic memory management, which provides memory initialization, allocation, release and other functions.

  • Dynamic memory: Allocates a user-specified chunk of memory in a dynamic memory pool. Advantages: Distribution according to needs. Disadvantages: Possible fragmentation in the memory pool.
  • Static memory: Allocates a block of memory in the static memory pool that is the preset (fixed) size at the time of user initialization. Advantages: High allocation and release efficiency, no fragmentation in static memory pool. Disadvantage: can only apply to the initialization of the preset size of the memory block, can not apply on demand.

This article focuses on the static Memory Box, and the dynamic Memory will be analyzed in the following series. Static memory is essentially a static array. The size of the block in the static memory pool is set during initialization. After initialization, the size of the block cannot be changed. The static memory pool consists of a control block and several memory blocks of the same size. The control block is located in the memory pool header and is used for memory block management. Memory blocks are applied and freed at block size granularity.

This article analyzes the source code of the static memory module to help the reader master the use of static memory. In this article the source involved in OpenHarmony LiteOS -m kernel, for example, can be in the open source site https://gitee.com/openharmony… To obtain.

Next, we look at the structure of static memory, static memory initialization, static memory common operation source code.

1. Static memory structure definition and common macro definition

1.1 Definition of static memory structures

The static memory structure is defined in the file kernel\include\los_membox.h. The source code is as follows: ⑴ defines LOS_MEMBOX_NODE structure, ⑵ defines LOS_MEMBOX_INFO structure of static memory pool, and the explanation of structure members can be found in the comment section.

⑴ typedef struct tagMEMBOX_NODE {struct tagMEMBOX_NODE *pstNext; /**< pointer to the next free node in the static memory pool */} LOS_MEMBOX_NODE; ⑵ typedef struct LOS_MEMBOX_INFO {UINT32 uwBlkSize; ⑵ typedef struct LOS_MEMBOX_INFO {UINT32 uwBlkSize; /**< static memory pool pointer to the next free node */ UINT32 uwBlkNum; /**< total number of blocks in static memory pool */ UINT32 uwBlkCnt; / * * (static memory pool, the total number of memory blocks allocated * / # if (LOSCFG_PLATFORM_EXC = = 1) struct LOS_MEMBOX_INFO * nextMemBox; /**< point to the next static memory pool */ #endif LOS_MEMBOX_NODE stFreelist; /**< LOS_MEMBOX_INFO; /**< LOS_MEMBOX_INFO;

The following diagram is used to illustrate the static memory. For a static memory region, the header is LOS_MEMBOX_INFO information, followed by each memory block, each memory block size is UWBLKSIZE, including the memory block node LOS_MEMBOX_NODEand the memory block data area. The free memory block node points to the next free memory block node.

1.2 Common definition of static memory macros

Some important macro definitions are also provided in the static memory header file. (1) LOS_MEMBOX_ALIGNED(memAddr) is used to align memory addresses, while OS_MEMBOX_NEXT(addr, blkSize) gets the memory address of the next memory block based on the current node memory address addr and the memory block size blkSize. ⑶ OS_MEMBOX_NODE_HEAD_SIZE represents the size of node nods in the memory block. Each memory block contains memory node LOS_MEMBOX_NODE and the data area where business is stored. Four indicates the total size of static memory, including the size of the memory pool information structure and the size of each memory block.

⑴ #define LOS_MEMBOX_ALIGNED(memAddr) (((UINTPTR) + sizeof(UINTPTR) -1) & (~(sizeof(UINTPTR) -1)) ⑵ #define (⑴ #define LOS_MEMBOX_ALIGNED(memAddr) ((UINTPTR) + sizeof(UINTPTR) -1)) ⑵ #define OS_MEMBOX_NEXT(addr, BlkSize)(LOS_MEMBOX_NODE *)(VOID *)((UINT8 *)(addr) + (blkSize)) ⑶ #define OS_MEMBOX_NODE_HEAD_SIZE Sizeof (LOS_MEMBOX_NODE) (4) # define LOS_MEMBOX_SIZE (blkSize, blkNum) \ (sizeof(LOS_MEMBOX_INFO) + (LOS_MEMBOX_ALIGNED((blkSize) + OS_MEMBOX_NODE_HEAD_SIZE) * (blkNum)))

Some macros and inline functions are also defined in the file kernel\ SRC \mm\los_membox.c. ⑴ The OS_MEMBOX_MAGIC magic word is defined. The last 8 bits of the 32-bit magic word maintain the task number information. The task number bit is defined by the macro at the ⑵. (3) The macro defines the maximum task number, and the macro at (4) extracts the task number information from the magic word.

⑸ inline function sets the magic word. After the memory block node is allocated from the static memory pool, the node pointer.pstnext no longer points to the next free memory block node, but is set to the magic word. The inline functions at the ends are used to verify magic words. The macro at ⑺ gets the data area address of the memory block according to the node address of the memory block. The macro at ⑻ gets the node address of the memory block according to the data area address of the memory block.

(1) # define OS_MEMBOX_MAGIC 0 xa55a5a00 2 # define OS_MEMBOX_TASKID_BITS 8 (3) # define OS_MEMBOX_MAX_TASKID ((1 < < OS_MEMBOX_TASKID_BITS) -1) ⑷ #define OS_MEMBOX_TASKID_GET(addr) (((UINTPTR)(addr)) & OS_MEMBOX_MAX_TASKID) ⑸ STATIC INLINE VOID OsMemBoxSetMagic(LOS_MEMBOX_NODE *node) { UINT8 taskID = (UINT8)LOS_CurTaskIDGet(); node->pstNext = (LOS_MEMBOX_NODE *)(OS_MEMBOX_MAGIC | taskID); } STATIC INLINE UINT32 osMemBoxCheckMagic (LOS_MEMBOX_NODE *node) {UINT32 tasKid = OS_MEMBOX_TASKID_GET(node->pstNext); if (taskID > (LOSCFG_BASE_CORE_TSK_LIMIT + 1)) { return LOS_NOK; } else { return (node->pstNext == (LOS_MEMBOX_NODE *)(OS_MEMBOX_MAGIC | taskID)) ? LOS_OK : LOS_NOK; }} ⑺ #define OS_MEMBOX_USER_ADDR(addr) \ ((VOID *)((UINT8 *)(addr) + OS_MEMBOX_NODE_HEAD_SIZE)) ⑻ #define OS_MEMBOX_NODE_ADDR(addr) \ ((LOS_MEMBOX_NODE *)(VOID *)((UINT8 *)(addr) - OS_MEMBOX_NODE_HEAD_SIZE))

2, static memory common operations

When the user needs to use a fixed length of memory, the memory can be obtained through static memory allocation, once the use is finished, through the static memory release function to return the occupied memory, so that it can be reused.

2.1 Initialize the static memory pool

Let’s look at the code that initializes the static memory pool function uint32los_memboxInit (VOID pool, UINT32 poolSize, UINT32 blkSize). VOID pool is the starting address of the static memory pool, UINT32 poolSize is the total size of the initialized static memory pool, poolSize must be less than or equal to the size of the memory area at the beginning of *pool, otherwise it will affect subsequent memory areas. You also need a header size larger than the sizeof static memory, sizeof(LOS_MEMBOX_INFO). Length UINT32 blkSize is the block size of each memory block in the static memory pool.

Let’s take a look at the code: ⑴ validates the parameters passed in. (2) Set the actual size of each memory block in the static memory pool, aligned with memory, and counting the information of nodes in the memory block. (3) calculates the total number of memory blocks in the memory pool, and then sets the number of used memory blocks. (4) If the available memory block is 0, the initialization failed. — Gets the first free memory block node in the memory pool. You mount the free memory blocks on stfreelist.pstnext, the static memory pool information structure, and then perform ⑺ where each free memory block points to the next free memory block in turn.

UINT32 LOS_MemboxInit(VOID *pool, UINT32 poolSize, UINT32 blkSize) { LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool; LOS_MEMBOX_NODE *node = NULL; UINT32 index; UINT32 intSave; ⑴ if (pool == NULL) {return LOS_NOK; } if (blkSize == 0) { return LOS_NOK; } if (poolSize < sizeof(LOS_MEMBOX_INFO)) { return LOS_NOK; } MEMBOX_LOCK(intSave); ⑵ boxinfo-> uwBlkSize = LOS_MEMBOX_ALIGNED(blkSize + OS_MEMBOX_NODE_HEAD_SIZE); ⑵ uwBlkSize = LOS_MEMBOX_ALIGNED(blkSize + OS_MEMBOX_NODE_HEAD_SIZE); if (boxInfo->uwBlkSize == 0) { MEMBOX_UNLOCK(intSave); return LOS_NOK; } ⑶ boxinfo-> uwblkNum = (poolsize-sizeof (LOS_MEMBOX_INFO))/boxinfo-> uwblkSize; boxInfo->uwBlkCnt = 0; ⑷ if (boxinfo-> uwBlkNum == 0) {MEMBOX_UNLOCK(intSave); return LOS_NOK; } ⑸ = (LOS_MEMBOX_NODE *)(boxInfo + 1); [6] boxInfo - > stFreeList. PstNext = node; ⑺ for (index = 0; index < boxInfo->uwBlkNum - 1; ++index) { node->pstNext = OS_MEMBOX_NEXT(node, boxInfo->uwBlkSize); node = node->pstNext; } node->pstNext = NULL; #if (LOSCFG_PLATFORM_EXC == 1) OsMemBoxAdd(pool); #endif MEMBOX_UNLOCK(intSave); return LOS_OK; }

2.2 Clear the contents of static memory blocks

We can use the function VOID LOS_MemboxClr(VOID pool, VOID box) to clear the contents of the data area from the static memory block, taking 2 arguments. The VOID pool is the initialized address of the static memory pool. VOID box: VOID box VOID box: VOID box VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box: VOID box Let’s analyze the source code.

(1) validates the parameters, and (2) calls memset_s() to write 0 to the memory block. The start address of the write is VOID *box, the start address of the data area of the memory block, and the length of the write is the length of the data area boxinfo-> uwblksize-os_membox_node_head_size.

VOID LOS_MemboxClr(VOID *pool, VOID *box) { LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool; (1) if ((pool = = NULL) | | (box = = NULL) {return; } ⑵ (VOID)memset_s(box, (boxinfo-> uwblksize-os_membox_node_head_size), 0, (boxInfo->uwBlkSize - OS_MEMBOX_NODE_HEAD_SIZE)); }

2.3 Apply and release static memory

After initializing the static memory pool, we can use the function VOID los_memboxAlloc (VOID pool) to claim the static memory.

⑴ Gets the head node of the list of free memory blocks in the static memory pool. If the list is not empty, execute ⑵ and assign the next available node to nodeTmp. ⑶ Execute the next linked list node of the next linked list node, and then execute ⑷ Set the magic word for the allocated memory block, and then increase the number of memory blocks used in the memory pool by 1. (5) Call the macro OS_MEMBOX_USER_ADDR() when returning to calculate the data region geology of the memory block.

VOID *LOS_MemboxAlloc(VOID *pool) { LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool; LOS_MEMBOX_NODE *node = NULL; LOS_MEMBOX_NODE *nodeTmp = NULL; UINT32 intSave; if (pool == NULL) { return NULL; } MEMBOX_LOCK(intSave); (1) the node = & (boxInfo - > stFreeList); if (node->pstNext ! = NULL) {⑵ nodeTmp = node->pstNext; (3) node - > pstNext = nodeTmp - > pstNext; (4) OsMemBoxSetMagic (nodeTmp); boxInfo->uwBlkCnt++; } MEMBOX_UNLOCK(intSave); ⑸ return (nodeTmp == NULL)? NULL : OS_MEMBOX_USER_ADDR(nodeTmp); }

When the block is used, we can use the function uint32los_memboxfree (VOID pool, VOID box) to free the static memory, taking 2 arguments. VOID pool is the initialized address of the static memory pool. The VOID box is the starting address of the data area of the static memory block that needs to be freed. Note that this is not the node address of the memory block. Let’s analyze the source code.

(1) Get the node address node according to the data area address of the memory block to be freed, and the memory block to be freed is first verified. (3) Hang the memory block to be freed on the list of free memory blocks in the memory pool, and then subtract 1 from the used number.

LITE_OS_SEC_TEXT UINT32 LOS_MemboxFree(VOID *pool, VOID *box) { LOS_MEMBOX_INFO *boxInfo = (LOS_MEMBOX_INFO *)pool; UINT32 ret = LOS_NOK; UINT32 intSave; if ((pool == NULL) || (box == NULL)) { return LOS_NOK; } MEMBOX_LOCK(intSave); Do {⑴ LOS_MEMBOX_NODE *node = OS_MEMBOX_NODE_ADDR(box); ⑵ if (osCheckBoxMem (boxInfo, node)! = LOS_OK) { break; } ⑶ node->pstNext = boxInfo-> stFreelist.pstnext; boxInfo->stFreeList.pstNext = node; (4) boxInfo - > uwBlkCnt -; ret = LOS_OK; } while (0); MEMBOX_UNLOCK(intSave); return ret; }

Next, let’s look at the check function osCheckBoxMem (). ⑴ If the size of the memory pool is 0, return validation failed. ⑵ Calculate the offset of the fast memory node to be released relative to the first memory block node. (3) If the offset is divided by the number of memory blocks, the remainder is not 0. (4) If the quotient of the offset divided by the number of memory blocks is greater than the number of memory blocks, the validation fails. ⑸ Check the magic word with the macro OSMEMBoxCheckMagic.

STATIC INLINE UINT32 OsCheckBoxMem(const LOS_MEMBOX_INFO *boxInfo, const VOID *node) { UINT32 offset; ⑴ if (boxinfo-> uwblkSize == 0) {return LOS_NOK; } ⑵ offset = (UINT32)((UINTPTR)node - (UINTPTR)(boxInfo + 1)); ⑶ if (offset % boxinfo-> uwBlkSize)! = 0) { return LOS_NOK; } ⑷ if (offset/boxinfo-> uwBlkSize) >= boxinfo-> uwBlkNum) {return LOS_NOK; } ⑸ return osMemboxCheckMagic ((LOS_MEMBOX_NODE *)node); }

summary

This article led us to analyze the HongMeng light kernel static memory module source code, including the structure of static memory, static memory pool initialization, static memory application, release, clear content, etc. Subsequent will launch more share articles, please look, also welcome you to share the experience of learning, light use HongMeng kernel and if you have any questions, Suggestions, can leave a message to us: https://gitee.com/openharmony… . In order to more easily find HongMeng kernel code warehouse, suggest to https://gitee.com/openharmony… , follow Watch, thumb up Star, and Fork to your account, thank you.

Click on the attention, the first time to understand Huawei cloud fresh technology ~