提交 586d289b 编写于 作者: A Annie_wang

update docs

Signed-off-by: NAnnie_wang <annie.wangli@huawei.com>
上级 781ff78e
...@@ -6,10 +6,7 @@ ...@@ -6,10 +6,7 @@
- Basic Kernel - Basic Kernel
- [Interrupt Management](kernel-mini-basic-interrupt.md) - [Interrupt Management](kernel-mini-basic-interrupt.md)
- [Task Management](kernel-mini-basic-task.md) - [Task Management](kernel-mini-basic-task.md)
- Memory Management - [Memory Management](kernel-mini-basic-memory.md)
- [Basic Concepts](kernel-mini-basic-memory-basic.md)
- [Static Memory](kernel-mini-basic-memory-static.md)
- [Dynamic Memory](kernel-mini-basic-memory-dynamic.md)
- Kernel Communication Mechanisms - Kernel Communication Mechanisms
- [Event](kernel-mini-basic-ipc-event.md) - [Event](kernel-mini-basic-ipc-event.md)
- [Mutex](kernel-mini-basic-ipc-mutex.md) - [Mutex](kernel-mini-basic-ipc-mutex.md)
...@@ -22,22 +19,15 @@ ...@@ -22,22 +19,15 @@
- [PUP](kernel-mini-extend-cpup.md) - [PUP](kernel-mini-extend-cpup.md)
- [Dynamic Loading](kernel-mini-extend-dynamic-loading.md) - [Dynamic Loading](kernel-mini-extend-dynamic-loading.md)
- [File System](kernel-mini-extend-file.md) - [File System](kernel-mini-extend-file.md)
- [FAT](kernel-mini-extend-file-fat.md)
- [LittleFS](kernel-mini-extend-file-lit.md)
- Kernel Debugging - Kernel Debugging
- [Memory Debugging](kernel-mini-memory-debug.md) - [Memory Debugging](kernel-mini-memory-debug.md)
- [Memory Information Statistics](kernel-mini-memory-debug-mes.md)
- [Memory Leak Check](kernel-mini-memory-debug-det.md)
- [Memory Corruption Check](kernel-mini-memory-debug-cet.md)
- [Exception Debugging](kernel-mini-memory-exception.md) - [Exception Debugging](kernel-mini-memory-exception.md)
- [Trace](kernel-mini-memory-trace.md) - [Trace](kernel-mini-memory-trace.md)
- [LMS](kernel-mini-memory-lms.md) - [LMS](kernel-mini-memory-lms.md)
- Appendix - Appendix
- [Kernel Coding Specification](kernel-mini-appx-code.md) - [Kernel Coding Specification](kernel-mini-appx-code.md)
- [Doubly Linked List](kernel-mini-appx-data-list.md) - [Doubly Linked List](kernel-mini-appx-data-list.md)
- Standard Libraries - [Standard Libraries](kernel-mini-appx-lib.md)
- [CMSIS Support](kernel-mini-appx-lib-cmsis.md)
- [POSIX support](kernel-mini-appx-lib-posix.md)
- Small-System Kernel - Small-System Kernel
- [Kernel Overview](kernel-small-overview.md) - [Kernel Overview](kernel-small-overview.md)
- Kernel Startup - Kernel Startup
...@@ -52,32 +42,27 @@ ...@@ -52,32 +42,27 @@
- Memory Management - Memory Management
- [Heap Memory Management](kernel-small-basic-memory-heap.md) - [Heap Memory Management](kernel-small-basic-memory-heap.md)
- [Physical Memory Management](kernel-small-basic-memory-physical.md) - [Physical Memory Management](kernel-small-basic-memory-physical.md)
- [Virtual Memory Management](kernel-small-basic-memory-virtual.md) - [Virtual Memory Management](kernel-small-basic-memory-virtual.md)
- [Virtual-to-Physical Mapping](kernel-small-basic-inner-reflect.md) - [Virtual-to-Physical Mapping](kernel-small-basic-inner-reflect.md)
- Kernel Communication Mechanisms - Kernel Communication Mechanisms
- [Event](kernel-small-basic-trans-event.md) - [Event](kernel-small-basic-trans-event.md)
- [Semaphore](kernel-small-basic-trans-semaphore.md) - [Semaphore](kernel-small-basic-trans-semaphore.md)
- [Mutex](kernel-small-basic-trans-mutex.md) - [Mutex](kernel-small-basic-trans-mutex.md)
- [Queue](kernel-small-basic-trans-queue.md) - [Queue](kernel-small-basic-trans-queue.md)
- [RW Lock](kernel-small-basic-trans-rwlock.md) - [RW Lock](kernel-small-basic-trans-rwlock.md)
- [Futex](kernel-small-basic-trans-user-mutex.md) - [Futex](kernel-small-basic-trans-user-mutex.md)
- [Signal](kernel-small-basic-trans-user-signal.md) - [Signal](kernel-small-basic-trans-user-signal.md)
- [Time Management](kernel-small-basic-time.md) - [Time Management](kernel-small-basic-time.md)
- [Software Timer](kernel-small-basic-softtimer.md) - [Software Timer](kernel-small-basic-softtimer.md)
- [Atomic Operation](kernel-small-basic-atomic.md) - [Atomic Operation](kernel-small-basic-atomic.md)
- Extension Components - Extension Components
- [System Call](kernel-small-bundles-system.md) - [System Call](kernel-small-bundles-system.md)
- [Dynamic Loading and Linking](kernel-small-bundles-linking.md) - [Dynamic Loading and Linking](kernel-small-bundles-linking.md)
- [Virtual Dynamic Shared Object](kernel-small-bundles-share.md) - [Virtual Dynamic Shared Object](kernel-small-bundles-share.md)
- [LiteIPC](kernel-small-bundles-ipc.md) - [LiteIPC](kernel-small-bundles-ipc.md)
- [File Systems](kernel-small-bundles-fs.md) - File Systems
- [Virtual File System](kernel-small-bundles-fs-virtual.md) - [Virtual File System](kernel-small-bundles-fs-virtual.md)
- Supported File Systems - [Supported File Systems](kernel-small-bundles-fs-support.md)
- [FAT](kernel-small-bundles-fs-support-fat.md)
- [JFFS2](kernel-small-bundles-fs-support-jffs2.md)
- [NFS](kernel-small-bundles-fs-support-nfs.md)
- [Ramfs](kernel-small-bundles-fs-support-ramfs.md)
- [Procfs](kernel-small-bundles-fs-support-procfs.md)
- [File System Adaptation](kernel-small-bundles-fs-new.md) - [File System Adaptation](kernel-small-bundles-fs-new.md)
- Debugging and Tools - Debugging and Tools
- Shell - Shell
...@@ -155,15 +140,7 @@ ...@@ -155,15 +140,7 @@
- [Memory Information Statistics](kernel-small-debug-memory-info.md) - [Memory Information Statistics](kernel-small-debug-memory-info.md)
- [Memory Leak Check](kernel-small-debug-memory-leak.md) - [Memory Leak Check](kernel-small-debug-memory-leak.md)
- [Memory Corruption Check](kernel-small-debug-memory-corrupt.md) - [Memory Corruption Check](kernel-small-debug-memory-corrupt.md)
- User-Mode Memory Debugging - [User-Mode Memory Debugging](kernel-small-debug-user.md)
- [Basic Concepts](kernel-small-debug-user-concept.md)
- [Working Principles](kernel-small-debug-user-function.md)
- Usage
- [Available APIs](kernel-small-debug-user-guide-api.md)
- [How to Use](kernel-small-debug-user-guide-use.md)
- [Calling APIs](kernel-small-debug-user-guide-use-api.md)
- [Using the CLI](kernel-small-debug-user-guide-use-cli.md)
- [Typical Memory Problems](kernel-small-debug-user-faqs.md)
- Other Kernel Debugging Methods - Other Kernel Debugging Methods
- [Dying Gasp](kernel-small-debug-trace-other-lastwords.md) - [Dying Gasp](kernel-small-debug-trace-other-lastwords.md)
- [Common Fault Locating Methods](kernel-small-debug-trace-other-faqs.md) - [Common Fault Locating Methods](kernel-small-debug-trace-other-faqs.md)
...@@ -176,8 +153,8 @@ ...@@ -176,8 +153,8 @@
- [Linux Kernel Overview](kernel-standard-overview.md) - [Linux Kernel Overview](kernel-standard-overview.md)
- [Applying Patches on Development Boards](kernel-standard-patch.md) - [Applying Patches on Development Boards](kernel-standard-patch.md)
- [Compiling and Building the Linux Kernel](kernel-standard-build.md) - [Compiling and Building the Linux Kernel](kernel-standard-build.md)
- [Enhanced Kernel Features](kernel-standard-enhanced-features.md) - Enhanced Kernel Features
- [Enhanced Swap](kernel-standard-mm-eswap.md) - [Enhanced Swap](kernel-standard-mm-eswap.md)
- [Task Scheduling](kernel-standard-sched.md) - Task Scheduling
- [Related Thread Group](kernel-standard-sched-rtg.md) - [Related Thread Group](kernel-standard-sched-rtg.md)
- [Lightweight CPU Isolation](kernel-standard-sched-cpuisolation.md) - [Lightweight CPU Isolation](kernel-standard-sched-cpuisolation.md)
\ No newline at end of file
# Appendix
- **[Kernel Coding Specification](kernel-mini-appx-code.md)**
- **[Doubly Linked List](kernel-mini-appx-data-list.md)**
- **[Standard Libraries](kernel-mini-appx-lib.md)**
# Basic Data Structure
- **[Doubly Linked List](kernel-mini-appx-data-list.md)**
# CMSIS Support
## Basic Concepts
The Cortex Microcontroller Software Interface Standard \([CMSIS](https://developer.arm.com/tools-and-software/embedded/cmsis)\) is a vendor-independent hardware abstraction layer for microcontrollers based on Arm Cortex processors. Of the CMSIS components, the Real Time Operating System \(RTOS\) defines a set of universal and standardized APIs to reduce the dependency of application developers on specific RTOS and facilitate software porting and reuse. The CMSIS provides CMSIS-RTOS v1 and CMSIS-RTOS v2. The OpenHarmony LiteOS-M supports only the implementation of CMSIS-RTOS v2.
## Development Guidelines
### Available APIs
The following table describes CMSIS-RTOS v2 APIs. For more details about the APIs, see the API reference.
**Table 1** CMSIS-RTOS v2 APIs
| Category| API| Description|
| -------- | -------- | -------- |
| Kernel information and control| osKernelGetInfo | Obtains RTOS kernel information.|
| | osKernelGetState | Obtains the current RTOS kernel status.|
| | osKernelGetSysTimerCount | Obtains the RTOS kernel system timer count.|
| | osKernelGetSysTimerFreq | Obtains the RTOS kernel system timer frequency.|
| | osKernelInitialize | Initializes the RTOS kernel.|
| | osKernelLock | Locks the RTOS kernel scheduler.|
| | osKernelUnlock | Unlocks the RTOS kernel scheduler.|
| | osKernelRestoreLock | Restores the RTOS kernel scheduler to the locked state.|
| | osKernelResume | Restores the RTOS kernel scheduler (not implemented yet).|
| | osKernelStart | Starts the RTOS kernel scheduler.|
| | osKernelSuspend | Suspends the RTOS kernel scheduler (not implemented yet).|
| | osKernelGetTickCount | Obtains the RTOS kernel tick count.|
| | osKernelGetTickFreq | Obtains the RTOS kernel tick frequency.|
| Thread management| osThreadDetach | Detaches a thread (to reclaim the thread storage when the thread terminates).|
| | osThreadEnumerate | Enumerates active threads (not been implemented yet).|
| | osThreadExit | Terminates a running thread.|
| | osThreadGetCount | Obtains the number of active threads.|
| | osThreadGetId | Obtains the ID of the running thread.|
| | osThreadGetName | Obtains the thread name.|
| | osThreadGetPriority | Obtains the current thread priority.|
| | osThreadGetStackSize | Obtains the thread stack size.|
| | osThreadGetStackSpace | Obtains the available stack space for a thread based on the stack waterline record during execution.|
| | osThreadGetState | Obtains the current thread status.|
| | osThreadJoin | Waits for the specified thread to terminate.|
| | osThreadNew | Creates a thread and adds it to active threads.|
| | osThreadResume | Resumes the execution of a thread.|
| | osThreadSetPriority | Changes the priority of a thread.|
| | osThreadSuspend | Suspends a thread.|
| | osThreadTerminate | Terminates a thread.|
| | osThreadYield | Passes control to the next thread in the ready state.|
| Thread flag| osThreadFlagsSet | Sets flags for a thread.|
| | osThreadFlagsClear | Clears the specified flags for the running thread.|
| | osThreadFlagsGet | Obtains the current flags of the running thread.|
| | osThreadFlagsWait | Waits for one or more thread flags of the running thread to signal.|
| Event flag| osEventFlagsGetName | Obtains the names of the event flags (not implemented yet).|
| | osEventFlagsNew | Creates and initializes event flags.|
| | osEventFlagsDelete | Deletes event flags.|
| | osEventFlagsSet | Sets event flags.|
| | osEventFlagsClear | Clears event flags.|
| | osEventFlagsGet | Obtains the current event flags.|
| | osEventFlagsWait | Waits for one or more event flags to be signaled.|
| General waiting functions| osDelay | Waits for timeout (time delay).|
| | osDelayUntil | Waits until the specified time.|
| Timer management| osTimerDelete | Deletes a timer.|
| | osTimerGetName | Obtains the timer name (not implemented yet).|
| | osTimerIsRunning | Checks whether a timer is running.|
| | osTimerNew | Creates and initializes a timer.|
| | osTimerStart | Starts or restarts a timer.|
| | osTimerStop | Stops a timer.|
| Mutex management| osMutexAcquire | Acquires a mutex or times out (if locked).|
| | osMutexDelete | Deletes a mutex.|
| | osMutexGetName | Obtains the mutex name (not implemented yet).|
| | osMutexGetOwner | Obtains the thread that acquires the mutex.|
| | osMutexNew | Creates and initializes a mutex.|
| | osMutexRelease | Releases the mutex obtained using **osMutexAcquire**.|
| Semaphore| osSemaphoreAcquire | Obtains the semaphore token or times out if no token is available.|
| | osSemaphoreDelete | Deletes a semaphore.|
| | osSemaphoreGetCount | Obtains the token count of the current semaphore.|
| | osSemaphoreGetName | Obtains the name of a semaphore (not implemented yet).|
| | osSemaphoreNew | Creates and initializes a semaphore.|
| | osSemaphoreRelease | Releases semaphore tokens till the initial maximum count.|
| Memory pool| osMemoryPoolAlloc | Allocates a memory block from the memory pool.|
| | osMemoryPoolDelete | Deletes a memory pool object.|
| | osMemoryPoolFree | Releases the allocated memory block to the memory pool.|
| | osMemoryPoolGetBlockSize | Obtains the memory block size in the memory pool.|
| | osMemoryPoolGetCapacity | Obtains the maximum number of memory blocks in the memory pool.|
| | osMemoryPoolGetCount | Obtains the number of used memory blocks in the memory pool.|
| | osMemoryPoolGetName | Obtains the memory pool name.|
| | osMemoryPoolGetSpace | Obtains the number of available memory blocks in the memory pool.|
| | osMemoryPoolNew | Creates and initializes a memory pool.|
| Message queue| osMessageQueueDelete | Deletes a message queue.|
| | osMessageQueueGet | Obtain a message from the queue or times out if the queue is empty.|
| | osMessageQueueGetCapacity | Obtains the maximum number of messages in the message queue.|
| | osMessageQueueGetCount | Obtains the number of queued messages in the message queue.|
| | osMessageQueueGetMsgSize | Obtains the maximum message size in the memory pool.|
| | osMessageQueueGetName | Obtains the message queue name (not implemented yet).|
| | osMessageQueueGetSpace | Obtains the number of slots available for messages in the message queue.|
| | osMessageQueueNew | Creates and initializes a message queue.|
| | osMessageQueuePut | Puts the message into the queue or times out if the queue is full.|
| | osMessageQueueReset | Initialized the message queue to the empty state (not implemented yet).|
### How to Develop
The CMSIS-RTOS v2 component can be provided as a library \(shown in the figure\) or source code. By adding the CMSIS-RTOS v2 component \(typically configuration files\), you can implement RTOS capabilities on CMSIS-based applications. You only need to include the **cmsis\_os2.h** header file. RTOS APIs can then be called to process RTOS kernel-related events. You do not need to recompile the source code when the kernel is replaced.
The RTOS object control block definition needs to be called for static object allocation. The implementation-specific header file \(**os\_xx.h** in the following figure\) provides access to such control block definitions. In the OpenHarmony LiteOS-M kernel, the header files whose names start with **los\_** provide the definitions of the kernel.
![](figures/how-to-develop.png)
### Development Example
```
#include ...
#include "cmsis_os2.h"
/*----------------------------------------------------------------------------
* Application main thread
*---------------------------------------------------------------------------*/
void app_main (void *argument) {
// ...
for (;;) {}
}
int main (void) {
// Initialize the system.
MySystemInit();
// ...
osKernelInitialize(); // Initialize CMSIS-RTOS.
osThreadNew(app_main, NULL, NULL); // Create the main thread of the application.
osKernelStart(); // Start to execute the thread.
for (;;) {}
}
```
# Kernel Communication Mechanisms
- **[Event](kernel-mini-basic-ipc-event.md)**
- **[Mutex](kernel-mini-basic-ipc-mutex.md)**
- **[Queue](kernel-mini-basic-ipc-queue.md)**
- **[Semaphore](kernel-mini-basic-ipc-sem.md)**
# Basic Concepts
Memory management, one of the core modules of the OS, manages the memory resources of the system. Memory management primarily involves initializing, allocating, and releasing memory.
While the OS is running, the memory management module manages the memory usage of users and the OS by allocating and releasing memory. This helps achieve the optimal memory usage and usage efficiency and minimize memory fragments.
The OpenHarmony LiteOS-M kernel memory management involves static and dynamic memory management, and provides functions such as memory initialization, allocation, and release.
- Dynamic memory: memory blocks of user-specified size allocated in the dynamic memory pool.
- Advantage: Resources are allocated on demand.
- Disadvantage: Fragments may occur in the memory pool.
- Static memory: memory blocks of the fixed size \(preset during initialization\) allocated in the static memory pool.
- Advantage: Memory is allocated and released efficiently, and there is no fragment in the static memory pool.
- Disadvantage: Only the memory blocks of the fixed size can be allocated. Memory cannot be allocated on demand.
# Dynamic Memory
## Working Principles
Dynamic memory management allows memory blocks of any size to be allocated from a large contiguous memory \(memory pool or heap memory\) configured in the system based on user demands when memory resources are sufficient. The memory block can be released for further use when not required. Compared with static memory management, dynamic memory management allows memory allocation on demand but causes fragmentation of memory.
The dynamic memory of the OpenHarmony LiteOS-M has optimized the memory space partitioning based on the Two-Level Segregate Fit \(TLSF\) algorithm to achieve higher performance and minimize fragmentation. The figure below shows the core algorithm of the dynamic memory.
**Figure 1** Dynamic memory algorithm for mini systems
![](figures/dynamic-memory-algorithm-for-mini-systems.png "dynamic-memory-algorithm-for-mini-systems")
Multiple free lists are used for management based on the size of the free memory block. The free memory blocks are divided into two parts: \[4, 127\] and \[2<sup>7</sup>, 2<sup>31</sup>\], as indicated by the size class in the above figure.
1. The memory in the range of \[4, 127\] \(lower part in the above figure) is divided into 31 parts. The size of the memory block corresponding to each part is a multiple of 4 bytes. Each part corresponds to a free list and a bit that indicates whether the free list is empty. The value **1** indicates that the free list is not empty. There are 31 bits corresponding to the 31 memory parts in the range of \[4, 127\].
2. The memory greater than 127 bytes is managed in power of two increments. The size of each range is \[2^n, 2^\(n+1\)-1\], where n is an integer in \[7, 30\]. This range is divided into 24 parts, each of which is further divided into 8 second-level \(L2\) ranges, as shown in Size Class and Size SubClass in the upper part of the above figure. Each L2 range corresponds to a free list and a bit that indicates whether the free list is empty. There are a total of 192 \(24 x 8\) L2 ranges, corresponding to 192 free lists and 192 bits.
For example, insert 40-byte free memory to a free list. The 40-byte free memory corresponds to the 10th free list in the range of \[40, 43\], and the 10th bit indicates the use of the free list. The system inserts the 40-byte free memory to the 10th free list and determines whether to update the bitmap flag. When 40-byte memory is requested, the system obtains the free list corresponding to the memory block of the requested size based on the bitmap flag, and then obtains a free memory node from the free list. If the size of the allocated node is greater than the memory requested, the system splits the node and inserts the remaining node to the free list. If 580-byte free memory needs to be inserted to a free list, the 580-byte free memory corresponds to the 47th \(31 + 2 x 8\) free list in L2 range \[2^9, 2^9+2^6\], and the 47th bit indicates the use of the free list. The system inserts the 580-byte free memory to the 47th free list and determines whether to update the bitmap flag. When 580-byte memory is requested, the system obtains the free list corresponding to the memory block of the requested size based on the bitmap flag, and then obtains a free memory node from the free list. If the size of the allocated node is greater than the memory requested, the system splits the node and inserts the remaining node to the free list. If the corresponding free list is empty, the system checks for a free list meeting the requirements in a larger memory range. In actual application, the system can locate the free list that meets the requirements at a time.
The figure below shows the memory management structure.
**Figure 2** Dynamic memory management structure for mini systems
![](figures/dynamic-memory-management-structure-for-mini-systems.png "dynamic-memory-management-structure-for-mini-systems")
- Memory pool header
The memory pool header contains the memory pool information, bitmap flag array, and free list array. The memory pool information includes the start address of the memory pool, total size of the heap memory, and attributes of the memory pool. The bitmap flag array consists of seven 32-bit unsigned integers. Each bit indicates whether the free list is inserted with free memory block nodes. The free list contains information about 223 free memory head nodes. The free memory head node information contains a memory node header and information about the previous and next nodes in the free list.
- Memory pool nodes
There are three types of nodes: free node, used node, and end node. Each memory node maintains the size and use flag of the memory node and a pointer to the previous memory node in the memory pool. The free nodes and used nodes have a data area, but the end node has no data area.
The off-chip physical memory needs to be used because the on-chip RAMs of some chips cannot meet requirements. The OpenHarmony LiteOS-M kernel can logically combine multiple discontiguous memory regions so that users are unaware of the discontiguous memory regions in the underlying layer. The OpenHarmony LiteOS-M kernel memory module inserts discontiguous memory regions into a free list as free memory nodes and marks the discontiguous parts as virtual memory nodes that have been used. In this way, the discontinuous memory regions are logically combined as a unified memory pool. The figure below shows how the discontiguous memory regions are logically integrated.
**Figure 3** Integrating discontiguous memory regions
![](figures/integrating-discontiguous-memory-regions.png "integrating-discontiguous-memory-regions")
The discontiguous memory regions are integrated into a unified memory pool as follows:
1. Call **LOS\_MemInit** to initialize the first memory region of multiple discontiguous memory regions.
2. <a name="li26042441209"></a>Obtain the start address and length of the next memory region, and calculate the **gapSize** between the current memory region and its previous memory region. The **gapSize** is considered as a used virtual node.
3. Set the size of the end node of the previous memory region to the sum of **gapSize** and **OS\_MEM\_NODE\_HEAD\_SIZE**.
4. <a name="li10604194419014"></a>Divide the current memory region into a free memory node and an end node, insert the free memory node to the free list, and set the link relationship between the nodes.
5. Repeat [2](#li26042441209) to [4](#li10604194419014) to integrate more discontiguous memory regions.
## Development Guidelines
### When to Use
Dynamic memory management allocates and manages memory resources requested by users dynamically. It is a good choice when users need memory blocks of different sizes. You can call the dynamic memory allocation function of the OS to request a memory block of the specified size. You can call the dynamic memory release function to release the memory at any time.
### Available APIs
The following table describes APIs available for OpenHarmony LiteOS-M dynamic memory management. For more details about the APIs, see the API reference.
**Table 1** APIs of the dynamic memory module
<a name="table1415203765610"></a>
<table><thead align="left"><tr id="row134151837125611"><th class="cellrowborder" valign="top" width="12.85128512851285%" id="mcps1.2.4.1.1"><p id="p16415637105612"><a name="p16415637105612"></a><a name="p16415637105612"></a>Function</p>
</th>
<th class="cellrowborder" valign="top" width="29.8029802980298%" id="mcps1.2.4.1.2"><p id="p11415163718562"><a name="p11415163718562"></a><a name="p11415163718562"></a>API</p>
</th>
<th class="cellrowborder" valign="top" width="57.34573457345735%" id="mcps1.2.4.1.3"><p id="p1641533755612"><a name="p1641533755612"></a><a name="p1641533755612"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row0415737175610"><td class="cellrowborder" rowspan="2" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p6485848217"><a name="p6485848217"></a><a name="p6485848217"></a>Initializing or deleting a memory pool</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p1448511481314"><a name="p1448511481314"></a><a name="p1448511481314"></a>LOS_MemInit</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p94857483110"><a name="p94857483110"></a><a name="p94857483110"></a>Initializes a dynamic memory pool of the specified size.</p>
</td>
</tr>
<tr id="row1841519376561"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p20485134810119"><a name="p20485134810119"></a><a name="p20485134810119"></a>LOS_MemDeInit</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p154851348113"><a name="p154851348113"></a><a name="p154851348113"></a>Deletes a memory pool. It is valid only when <strong id="b68821856145419"><a name="b68821856145419"></a><a name="b68821856145419"></a>LOSCFG_MEM_MUL_POOL</strong> is enabled.</p>
</td>
</tr>
<tr id="row1187514443616"><td class="cellrowborder" rowspan="4" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p19661710214"><a name="p19661710214"></a><a name="p19661710214"></a>Allocating or releasing dynamic memory</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p66111714213"><a name="p66111714213"></a><a name="p66111714213"></a>LOS_MemAlloc</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p4661715214"><a name="p4661715214"></a><a name="p4661715214"></a>Allocates memory of the specified size from the dynamic memory pool.</p>
</td>
</tr>
<tr id="row1745415527441"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p116111718218"><a name="p116111718218"></a><a name="p116111718218"></a>LOS_MemFree</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1569175218"><a name="p1569175218"></a><a name="p1569175218"></a>Releases the memory allocated from the specified dynamic memory.</p>
</td>
</tr>
<tr id="row19101718144518"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p161417225"><a name="p161417225"></a><a name="p161417225"></a>LOS_MemRealloc</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p56181718219"><a name="p56181718219"></a><a name="p56181718219"></a>Re-allocates a memory block of the required size and copies data from the original block to the newly allocated bock. If the new memory block is successfully allocated, the original memory block will be released.</p>
</td>
</tr>
<tr id="row1346314166464"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p10610171528"><a name="p10610171528"></a><a name="p10610171528"></a>LOS_MemAllocAlign</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p26171714214"><a name="p26171714214"></a><a name="p26171714214"></a>Allocates the memory of the specified size and aligned based on the specified bytes from a dynamic memory pool.</p>
</td>
</tr>
<tr id="row28531740101112"><td class="cellrowborder" rowspan="4" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p39818810129"><a name="p39818810129"></a><a name="p39818810129"></a>Obtaining memory pool information</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p16981986123"><a name="p16981986123"></a><a name="p16981986123"></a>LOS_MemPoolSizeGet</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p129820881212"><a name="p129820881212"></a><a name="p129820881212"></a>Obtains the total size of the specified dynamic memory pool.</p>
</td>
</tr>
<tr id="row34281341171114"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p0987831214"><a name="p0987831214"></a><a name="p0987831214"></a>LOS_MemTotalUsedGet</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1598889124"><a name="p1598889124"></a><a name="p1598889124"></a>Obtains the total memory usage of the specified dynamic memory pool.</p>
</td>
</tr>
<tr id="row112644551119"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p398208201215"><a name="p398208201215"></a><a name="p398208201215"></a>LOS_MemInfoGet</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p139815820126"><a name="p139815820126"></a><a name="p139815820126"></a>Obtains the memory structure information of the specified memory pool, including the free memory, used memory, number of free memory blocks, number of used memory blocks, and maximum size of the free memory block.</p>
</td>
</tr>
<tr id="row1357684518110"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p3981383125"><a name="p3981383125"></a><a name="p3981383125"></a>LOS_MemPoolList</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p998148101218"><a name="p998148101218"></a><a name="p998148101218"></a>Prints information about all initialized memory pools in the system, including the start address, size, total free memory, used memory, maximum size of the free memory block, number of free memory blocks, and number of used memory blocks of each memory pool. It is valid only when <strong id="b899016549611"><a name="b899016549611"></a><a name="b899016549611"></a>LOSCFG_MEM_MUL_POOL</strong> is enabled.</p>
</td>
</tr>
<tr id="row14824879135"><td class="cellrowborder" rowspan="2" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p1058973361319"><a name="p1058973361319"></a><a name="p1058973361319"></a>Obtaining memory block information</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p989115206287"><a name="p989115206287"></a><a name="p989115206287"></a>LOS_MemFreeNodeShow</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p437618158141"><a name="p437618158141"></a><a name="p437618158141"></a>Prints the size and number of free memory blocks in the specified memory pool.</p>
</td>
</tr>
<tr id="row525917259143"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p0260025151415"><a name="p0260025151415"></a><a name="p0260025151415"></a>LOS_MemUsedNodeShow</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p19976124812146"><a name="p19976124812146"></a><a name="p19976124812146"></a>Prints the size and number of used memory blocks in the specified memory pool.</p>
</td>
</tr>
<tr id="row0715201211155"><td class="cellrowborder" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p13599202711513"><a name="p13599202711513"></a><a name="p13599202711513"></a>Checking memory pool integrity</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p5784183891513"><a name="p5784183891513"></a><a name="p5784183891513"></a>LOS_MemIntegrityCheck</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p15644611153"><a name="p15644611153"></a><a name="p15644611153"></a>Checks the integrity of the specified memory pool. It is valid only when <strong id="b1215338788"><a name="b1215338788"></a><a name="b1215338788"></a>LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK</strong> is enabled.</p>
</td>
</tr>
<tr id="row179965317318"><td class="cellrowborder" valign="top" width="12.85128512851285%" headers="mcps1.2.4.1.1 "><p id="p205321491738"><a name="p205321491738"></a><a name="p205321491738"></a>Adding discontiguous memory regions</p>
</td>
<td class="cellrowborder" valign="top" width="29.8029802980298%" headers="mcps1.2.4.1.2 "><p id="p1532399316"><a name="p1532399316"></a><a name="p1532399316"></a>LOS_MemRegionsAdd</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p20532149635"><a name="p20532149635"></a><a name="p20532149635"></a>Logically integrates multiple discontiguous memory regions into a unified memory pool. It is valid only when <strong id="b139814570571"><a name="b139814570571"></a><a name="b139814570571"></a>LOSCFG_MEM_MUL_REGIONS</strong> is enabled. If the memory pool pointer parameter <strong id="b193777151040"><a name="b193777151040"></a><a name="b193777151040"></a>pool</strong> is empty, initialize the first of the multiple memory regions in the memory pool and insert other memory regions as free nodes. If <strong id="b12330104011612"><a name="b12330104011612"></a><a name="b12330104011612"></a>pool</strong> is not empty, insert the multiple memory regions into the specified memory pool as free nodes.</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>- The dynamic memory module manages memory through control block structures, which consume extra memory. Therefore, the actual memory space available to users is less than the value of **OS\_SYS\_MEM\_SIZE**.
>- The **LOS\_MemAllocAlign** and **LOS\_MemMallocAlign** APIs consume extra memory for memory alignment, which may cause memory loss. When the memory used for alignment is freed up, the lost memory will be reclaimed.
>- The discontiguous memory regions passed by the **LosMemRegion** array to the **LOS\_MemRegionsAdd** API must be sorted in ascending order by memory start address in memory regions, and the memory regions cannot overlap.
### How to Develop
The typical development process of dynamic memory is as follows:
1. Call the **LOS\_MemInit** API to initialize a memory pool.
After a memory pool is initialized, a memory pool control header and end node will be generated, and the remaining memory is marked as free nodes. The end node is the last node in the memory pool, and its size is **0**.
1. Call the **LOS\_MemAlloc** API to allocate dynamic memory of any size.
The system checks whether the dynamic memory pool has free memory blocks greater than the requested size. If yes, the system allocates a memory block and returns the pointer to the memory block. If no, the system returns NULL. If the memory block allocated is greater than the requested size, the system splits the memory block and inserts the remaining memory block to the free list.
1. Call the **LOS\_MemFree** API to release dynamic memory.
The released memory block can be reused. When **LOS\_MemFree** is called, the memory block will be reclaimed and marked as free nodes. When memory blocks are reclaimed, adjacent free nodes are automatically merged.
### Development Example
This example implements the following:
1. Initialize a dynamic memory pool.
2. Allocate a memory block from the dynamic memory pool.
3. Store a piece of data in the memory block.
4. Print the data in the memory block.
5. Release the memory block.
The sample code is as follows:
```
#include "los_memory.h"
#define TEST_POOL_SIZE (2*1024)
__attribute__((aligned(4))) UINT8 g_testPool[TEST_POOL_SIZE];
VOID Example_DynMem(VOID)
{
UINT32 *mem = NULL;
UINT32 ret;
/* Initialize the memory pool. */
ret = LOS_MemInit(g_testPool, TEST_POOL_SIZE);
if (LOS_OK == ret) {
printf("Mem init success!\n");
} else {
printf("Mem init failed!\n");
return;
}
/* Allocate memory.*/
mem = (UINT32 *)LOS_MemAlloc(g_testPool, 4);
if (NULL == mem) {
printf("Mem alloc failed!\n");
return;
}
printf("Mem alloc success!\n");
/* Assign a value.*/
*mem = 828;
printf("*mem = %d\n", *mem);
/* Release memory.*/
ret = LOS_MemFree(g_testPool, mem);
if (LOS_OK == ret) {
printf("Mem free success!\n");
} else {
printf("Mem free failed!\n");
}
return;
}
```
### Verification
The output is as follows:
```
Mem init success!
Mem alloc success!
*mem = 828
Mem free success!
```
# Static Memory
## Working Principles
The static memory is a static array. The block size in the static memory pool is set during initialization and cannot be changed after initialization.
The static memory pool consists of a control block **LOS\_MEMBOX\_INFO** and several memory blocks **LOS\_MEMBOX\_NODE** of the same size. The control block is located at the head of the memory pool and used for memory block management. It contains the memory block size \(**uwBlkSize**\), number of memory blocks \(**uwBlkNum**\), number of allocated memory blocks \(**uwBlkCnt**\), and free list \(**stFreeList**\). Memory is allocated and released by block size. Each memory block contains the pointer **pstNext** that points to the next memory block.
**Figure 1** Static memory
![](figures/static-memory.png "static-memory")
## Development Guidelines
### When to Use
Use static memory allocation to obtain memory blocks of the fixed size. When the memory is no longer required, release the static memory.
### Available APIs
The following table describes APIs available for OpenHarmony LiteOS-M static memory management. For more details about the APIs, see the API reference.
**Table 1** APIs of the static memory module
<a name="table1415203765610"></a>
<table><thead align="left"><tr id="row134151837125611"><th class="cellrowborder" valign="top" width="16.19161916191619%" id="mcps1.2.4.1.1"><p id="p16415637105612"><a name="p16415637105612"></a><a name="p16415637105612"></a>Function</p>
</th>
<th class="cellrowborder" valign="top" width="22.472247224722473%" id="mcps1.2.4.1.2"><p id="p11415163718562"><a name="p11415163718562"></a><a name="p11415163718562"></a>API</p>
</th>
<th class="cellrowborder" valign="top" width="61.33613361336133%" id="mcps1.2.4.1.3"><p id="p1641533755612"><a name="p1641533755612"></a><a name="p1641533755612"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row0415737175610"><td class="cellrowborder" valign="top" width="16.19161916191619%" headers="mcps1.2.4.1.1 "><p id="p2990613114416"><a name="p2990613114416"></a><a name="p2990613114416"></a>Initializing the static memory pool</p>
</td>
<td class="cellrowborder" valign="top" width="22.472247224722473%" headers="mcps1.2.4.1.2 "><p id="p169901113194416"><a name="p169901113194416"></a><a name="p169901113194416"></a>LOS_MemboxInit</p>
</td>
<td class="cellrowborder" valign="top" width="61.33613361336133%" headers="mcps1.2.4.1.3 "><p id="p5990113174414"><a name="p5990113174414"></a><a name="p5990113174414"></a>Initialize a static memory pool and sets the start address, total size, and size of each memory block based on the input parameters.</p>
</td>
</tr>
<tr id="row1841519376561"><td class="cellrowborder" valign="top" width="16.19161916191619%" headers="mcps1.2.4.1.1 "><p id="p9367164904413"><a name="p9367164904413"></a><a name="p9367164904413"></a>Clearing static memory blocks</p>
</td>
<td class="cellrowborder" valign="top" width="22.472247224722473%" headers="mcps1.2.4.1.2 "><p id="p103671549144411"><a name="p103671549144411"></a><a name="p103671549144411"></a>LOS_MemboxClr</p>
</td>
<td class="cellrowborder" valign="top" width="61.33613361336133%" headers="mcps1.2.4.1.3 "><p id="p18367184916448"><a name="p18367184916448"></a><a name="p18367184916448"></a>Clears the memory blocks allocated from the static memory pool.</p>
</td>
</tr>
<tr id="row1187514443616"><td class="cellrowborder" rowspan="2" valign="top" width="16.19161916191619%" headers="mcps1.2.4.1.1 "><p id="p64541711458"><a name="p64541711458"></a><a name="p64541711458"></a>Allocating or releasing static memory</p>
</td>
<td class="cellrowborder" valign="top" width="22.472247224722473%" headers="mcps1.2.4.1.2 "><p id="p84547710452"><a name="p84547710452"></a><a name="p84547710452"></a>LOS_MemboxAlloc</p>
</td>
<td class="cellrowborder" valign="top" width="61.33613361336133%" headers="mcps1.2.4.1.3 "><p id="p5454177164520"><a name="p5454177164520"></a><a name="p5454177164520"></a>Allocates a memory block from a specified static memory pool.</p>
</td>
</tr>
<tr id="row1745415527441"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p645457204512"><a name="p645457204512"></a><a name="p645457204512"></a>LOS_MemboxFree</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p545415704514"><a name="p545415704514"></a><a name="p545415704514"></a>Releases a memory block allocated from the static memory pool.</p>
</td>
</tr>
<tr id="row19101718144518"><td class="cellrowborder" rowspan="2" valign="top" width="16.19161916191619%" headers="mcps1.2.4.1.1 "><p id="p15927427144615"><a name="p15927427144615"></a><a name="p15927427144615"></a>Obtaining or printing static memory pool information</p>
</td>
<td class="cellrowborder" valign="top" width="22.472247224722473%" headers="mcps1.2.4.1.2 "><p id="p792715277464"><a name="p792715277464"></a><a name="p792715277464"></a>LOS_MemboxStatisticsGet</p>
</td>
<td class="cellrowborder" valign="top" width="61.33613361336133%" headers="mcps1.2.4.1.3 "><p id="p139271327114620"><a name="p139271327114620"></a><a name="p139271327114620"></a>Obtains information about a specified static memory pool, including the total number of memory blocks in the memory pool, number of allocated memory blocks, and size of each memory block.</p>
</td>
</tr>
<tr id="row1346314166464"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p8927102754619"><a name="p8927102754619"></a><a name="p8927102754619"></a>LOS_ShowBox</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p49274279460"><a name="p49274279460"></a><a name="p49274279460"></a>Prints information about all nodes in a specified static memory pool (the print level is <strong id="b1937798153019"><a name="b1937798153019"></a><a name="b1937798153019"></a>LOS_INFO_LEVEL</strong>). The information includes the start address of the memory pool, memory block size, total number of memory blocks, start address of each idle memory block, and start addresses of all memory blocks.</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
>The number of memory blocks in the memory pool after initialization is not equal to the total memory size divided by the memory block size. The reason is the control block of the memory pool and the control header of each memory block have memory overheads. When setting the total memory size, you need to consider these factors.
### How to Develop
The typical development process of static memory is as follows:
1. Plan a memory space as the static memory pool.
2. Call the **LOS\_MemboxInit** API to initialize the static memory pool.
During initialization, the memory space specified by the input parameter is divided into multiple blocks \(the number of blocks depends on the total static memory size and the block size\). Insert all memory blocks to the free list, and place the control header at the beginning of the memory.
3. Call the **LOS\_MemboxAlloc** API to allocate static memory.
The system allocates the first free memory block from the free list and returns the start address of this memory block.
4. Call the **LOS\_MemboxClr** API.
Clear the memory block corresponding to the address contained in the input parameter.
5. Call the **LOS\_MemboxFree** API.
Add the memory block to the free list.
### Development Example
This example implements the following:
1. Initialize a static memory pool.
2. Allocate a memory block from the static memory pool.
3. Store a piece of data in a memory block.
4. Print the data in the memory block.
5. Clear the data in the memory block.
6. Release the memory block.
The sample code is as follows:
```
#include "los_membox.h"
VOID Example_StaticMem(VOID)
{
UINT32 *mem = NULL;
UINT32 blkSize = 10;
UINT32 boxSize = 100;
UINT32 boxMem[1000];
UINT32 ret;
/* Initialize the memory pool.*/
ret = LOS_MemboxInit(&boxMem[0], boxSize, blkSize);
if(ret != LOS_OK) {
printf("Membox init failed!\n");
return;
} else {
printf("Membox init success!\n");
}
/* Request a memory block.*/
mem = (UINT32 *)LOS_MemboxAlloc(boxMem);
if (NULL == mem) {
printf("Mem alloc failed!\n");
return;
}
printf("Mem alloc success!\n");
/* Assign a value.*/
*mem = 828;
printf("*mem = %d\n", *mem);
/* Clear data in the memory block. */
LOS_MemboxClr(boxMem, mem);
printf("Mem clear success \n *mem = %d\n", *mem);
/* Release the memory.*/
ret = LOS_MemboxFree(boxMem, mem);
if (LOS_OK == ret) {
printf("Mem free success!\n");
} else {
printf("Mem free failed!\n");
}
return;
}
```
### Verification
The output is as follows:
```
Membox init success!
Mem alloc success!
*mem = 828
Mem clear success
*mem = 0
Mem free success!
```
# Memory Management # Memory Management
## Basic Concepts
- **[Basic Concepts](kernel-mini-basic-memory-basic.md)**
- **[Static Memory](kernel-mini-basic-memory-static.md)** Memory management, one of the core modules of the OS, manages the memory resources of the system. Memory management primarily involves initializing, allocating, and releasing memory.
- **[Dynamic Memory](kernel-mini-basic-memory-dynamic.md)**
While the OS is running, the memory management module manages the memory usage of users and the OS by allocating and releasing memory. This helps achieve the optimal memory usage and usage efficiency and minimize memory fragments.
The OpenHarmony LiteOS-M kernel memory management involves static and dynamic memory management, and provides functions such as memory initialization, allocation, and release.
- Dynamic memory: memory blocks of user-specified size allocated in the dynamic memory pool.
- Advantage: Resources are allocated on demand.
- Disadvantage: Fragments may occur in the memory pool.
- Static memory: memory blocks of the fixed size (preset during initialization) allocated in the static memory pool.
- Advantage: Memory is allocated and released efficiently, and there is no memory fragment in the memory pool.
- Disadvantage: Only the memory blocks of the fixed size can be allocated. Memory cannot be allocated on demand.
## Static Memory
### Working Principles
The static memory is a static array. The block size in the static memory pool is set during initialization and cannot be changed after initialization.
The static memory pool consists of a control block **LOS_MEMBOX_INFO** and several memory blocks **LOS_MEMBOX_NODE** of the same size. The control block is located at the head of the memory pool and used for memory block management. It contains the memory block size (**uwBlkSize**), number of memory blocks (**uwBlkNum**), number of allocated memory blocks (**uwBlkCnt**), and free list (**stFreeList**). Memory is allocated and released by block. Each memory block contains the pointer **pstNext** that points to the next memory block.
**Figure 1** Static memory
![](figures/static-memory.png "static-memory")
### Development Guidelines
#### When to Use
Use static memory allocation to obtain memory blocks of the fixed size. When the memory is no longer required, release the static memory.
#### Available APIs
The following table describes APIs available for OpenHarmony LiteOS-M static memory management. For more details about the APIs, see the API reference.
**Table 1** APIs of the static memory module
| Category| API|
| -------- | -------- |
| Initializing the static memory pool| **LOS_MemboxInit**: initializes a static memory pool, that is, sets the start address, total size, and size of each memory block based on input parameters.|
| Clearing static memory blocks| **LOS_MemboxClr**: clears the memory blocks allocated from the static memory pool.|
| Allocating or releasing static memory| - **LOS_MemboxAlloc**: allocates a memory block from a specified static memory pool.<br>- **LOS_MemboxFree**: releases a memory block allocated from the static memory pool.|
| Obtaining or printing static memory pool information| - **LOS_MemboxStatisticsGet**: obtains information about a specified static memory pool, including the total number of memory blocks in the memory pool, number of allocated memory blocks, and size of each memory block.<br>- **LOS_ShowBox**: prints information about all nodes in a specified static memory pool (the print level is **LOS_INFO_LEVEL**). The information includes the start address of the memory pool, memory block size, total number of memory blocks, start address of each idle memory block, and start addresses of all memory blocks.|
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> The number of memory blocks in the memory pool after initialization is not equal to the total memory size divided by the memory block size. The reason is the control block of the memory pool and the control header of each memory block have memory overheads. When setting the total memory size, you need to consider these factors.
#### How to Develop
The typical development process of static memory is as follows:
1. Plan a memory area as a static memory pool.
2. Call **LOS_MemboxInit** to initialize the static memory pool.
During initialization, the memory space specified by the input parameter is divided into multiple blocks (the number of blocks depends on the total static memory size and the block size). Insert all memory blocks to the free list, and place the control header at the beginning of the memory.
3. Call **LOS_MemboxAlloc** to allocate the static memory.
The system obtains the first free block from the free list and returns the start address of the memory block.
4. Call **LOS_MemboxClr**.
Clear the memory block corresponding to the address contained in the input parameter.
5. Call **LOS_MemboxFree**.
Add the memory block to the free list.
#### Development Example
This example implements the following:
1. Initialize a static memory pool.
2. Allocate a memory block from the static memory pool.
3. Store a piece of data in a memory block.
4. Print the data in the memory block.
5. Clear the data in the memory block.
6. Release the memory block.
The sample code is as follows:
```
#include "los_membox.h"
VOID Example_StaticMem(VOID)
{
UINT32 *mem = NULL;
UINT32 blkSize = 10;
UINT32 boxSize = 100;
UINT32 boxMem[1000];
UINT32 ret;
/* Initialize the memory pool. */
ret = LOS_MemboxInit(&boxMem[0], boxSize, blkSize);
if(ret != LOS_OK) {
printf("Membox init failed!\n");
return;
} else {
printf("Membox init success!\n");
}
/* Request a memory block. */
mem = (UINT32 *)LOS_MemboxAlloc(boxMem);
if (NULL == mem) {
printf("Mem alloc failed!\n");
return;
}
printf("Mem alloc success!\n");
/* Assign a value. */
*mem = 828;
printf("*mem = %d\n", *mem);
/* Clear the memory. */
LOS_MemboxClr(boxMem, mem);
printf("Mem clear success \n *mem = %d\n", *mem);
/ Release the memory. */
ret = LOS_MemboxFree(boxMem, mem);
if (LOS_OK == ret) {
printf("Mem free success!\n");
} else {
printf("Mem free failed!\n");
}
return;
}
```
#### Verification
The output is as follows:
```
Membox init success!
Mem alloc success!
*mem = 828
Mem clear success
*mem = 0
Mem free success!
```
## Dynamic Memory
### Working Principles
Dynamic memory management allows memory blocks of any size to be allocated from a large contiguous memory (memory pool or heap memory) configured in the system based on user demands when memory resources are sufficient. The memory block can be released for further use when not required. Compared with static memory management, dynamic memory management allows memory allocation on demand but causes fragmentation of memory.
The dynamic memory of the OpenHarmony LiteOS-M has optimized the memory space partitioning based on the Two-Level Segregate Fit (TLSF) algorithm to achieve higher performance and minimize fragmentation. The figure below shows the core algorithm of the dynamic memory.
**Figure 1** Dynamic memory algorithm for mini systems
![](figures/dynamic-memory-algorithm-for-mini-systems.png "dynamic-memory-algorithm-for-mini-systems")
Multiple free lists are used for management based on the size of the free memory block. The free memory blocks are divided into two parts: [4, 127] and [2<sup>7</sup>, 2<sup>31</sup>], as indicated by the size class in the above figure.
1. The memory in the range of [4, 127] (lower part in the figure) is equally divided into 31 parts. The size of the memory block corresponding to each part is a multiple of 4 bytes. Each part corresponds to a free list and a bit that indicates whether the free list is empty. The value **1** indicates that the free list is not empty. There are 31 bits corresponding to the 31 memory parts in the range of [4, 127].
2. The memory greater than 127 bytes is managed in power of two increments. The size of each range is [2^n, 2^(n+1) -1], where n is an integer in [7, 30]. This range is divided into 24 parts, each of which is further divided into 8 second-level (L2) ranges, as shown in Size Class and Size SubClass in the upper part of the figure. Each L2 range corresponds to a free list and a bit that indicates whether the free list is empty. There are a total of 192 (24 x 8) L2 ranges, corresponding to 192 free lists and 192 bits.
For example, insert 40-byte free memory to a free list. The 40-byte free memory corresponds to the 10th free list in the range of [40, 43], and the 10th bit indicates the use of the free list. The system inserts the 40-byte free memory to the 10th free list and determines whether to update the bitmap flag. When 40-byte memory is requested, the system obtains the free list corresponding to the memory block of the requested size based on the bitmap flag, and then obtains a free memory node from the free list. If the size of the allocated node is greater than the memory requested, the system splits the node and inserts the remaining node to the free list.
If 580-byte free memory needs to be inserted to a free list, the 580-byte free memory corresponds to the 47th (31 + 2 x 8) free list in L2 range [2^9, 2^9+2^6], and the 47th bit indicates the use of the free list. The system inserts the 580-byte free memory to the 47th free list and determines whether to update the bitmap flag. When 580-byte memory is requested, the system obtains the free list corresponding to the memory block of the requested size based on the bitmap flag, and then obtains a free memory node from the free list. If the size of the allocated node is greater than the memory requested, the system splits the node and inserts the remaining node to the free list. If the corresponding free list is empty, the system checks for a free list meeting the requirements in a larger memory range. In actual application, the system can locate the free list that meets the requirements at a time.
The figure below shows the memory management structure.
**Figure 2** Dynamic memory management structure for mini systems
![](figures/dynamic-memory-management-structure-for-mini-systems.png "dynamic-memory-management-structure-for-mini-systems")
- Memory pool header
The memory pool header contains the memory pool information, bitmap flag array, and free list array. The memory pool information includes the start address of the memory pool, total size of the heap memory, and attributes of the memory pool. The bitmap flag array consists of seven 32-bit unsigned integers. Each bit indicates whether the free list is inserted with free memory block nodes. The free list contains information about 223 free memory head nodes. The free memory head node information contains a memory node header and information about the previous and next nodes in the free list.
- Memory pool nodes
There are three types of nodes: free node, used node, and end node. Each memory node maintains the size and use flag of the memory node and a pointer to the previous memory node in the memory pool. The free nodes and used nodes have a data area, but the end node has no data area.
The off-chip physical memory needs to be used because the on-chip RAMs of some chips cannot meet requirements. The OpenHarmony LiteOS-M kernel can logically combine multiple discontiguous memory regions so that users are unaware of the discontiguous memory regions in the underlying layer. The OpenHarmony LiteOS-M kernel memory module inserts discontiguous memory regions into a free list as free memory nodes and marks the discontiguous parts as virtual memory nodes that have been used. In this way, the discontinuous memory regions are logically combined as a unified memory pool.
The figure below shows how the discontiguous memory regions are logically integrated.
**Figure 3** Integrating discontiguous memory regions
![](figures/integrating-discontiguous-memory-regions.png "integrating-discontiguous-memory-regions")
The discontiguous memory regions are integrated into a unified memory pool as follows:
1. Call **LOS_MemInit** to initialize the first memory region of multiple discontiguous memory regions.
2. Obtain the start address and length of the next memory region, and calculate the **gapSize** between the current memory region and its previous memory region. The **gapSize** is considered as a used virtual node.
3. Set the size of the end node of the previous memory region to the sum of **gapSize** and **OS_MEM_NODE_HEAD_SIZE**.
4. Divide the current memory region into a free memory node and an end node, insert the free memory node to the free list, and set the link relationship between the nodes.
5. Repeat 2 to 4 to integrate more discontiguous memory regions.
### Development Guidelines
#### When to Use
Dynamic memory management allocates and manages memory resources requested by users dynamically. It is a good choice when users need memory blocks of different sizes. You can call the dynamic memory allocation function of the OS to request a memory block of the specified size. You can call the dynamic memory release function to release the memory at any time.
#### Available APIs
The following table describes APIs available for OpenHarmony LiteOS-M dynamic memory management. For more details about the APIs, see the API reference.
**Table 1** APIs of the dynamic memory module
| Category| Description|
| -------- | -------- |
| Initializing or deleting a memory pool| - **LOS_MemInit**: initializes a dynamic memory pool of the specified size.<br>- **LOS_MemDeInit**: deletes a memory pool. It is valid only when **LOSCFG_MEM_MUL_POOL** is enabled.|
| Allocating or releasing dynamic memory| - **LOS_MemAlloc**: allocates memory of the specified size from the dynamic memory pool.<br>- **LOS_MemFree**: releases the memory allocated from the specified dynamic memory.<br>- **LOS_MemRealloc**: re-allocates a memory block of the required size and copies data from the original block to the newly allocated bock. If the new memory block is successfully allocated, the original memory block will be released.|
| Obtaining memory pool information| - **LOS_MemPoolSizeGet**: obtains the total size of the specified dynamic memory pool.<br>- **LOS_MemTotalUsedGet**: obtains the total memory usage of the specified dynamic memory pool.<br>- **LOS_MemInfoGet**: obtains the memory structure information of the specified memory pool, including the free memory, used memory, number of free memory blocks, number of used memory blocks, and maximum size of the free memory block.<br>- **LOS_MemPoolList**: prints information about all initialized memory pools in the system, including the start address, size, total free memory, used memory, maximum size of the free memory block, number of free memory blocks, and number of used memory blocks of each memory pool. It is valid only when **LOSCFG_MEM_MUL_POOL** is enabled. |
| Obtaining memory block information| - **LOS_MemFreeNodeShow**: prints the size and number of free memory blocks in the specified memory pool.<br>- **LOS_MemUsedNodeShow**: prints the size and number of used memory blocks in the specified memory pool.|
| Checking memory pool integrity| **LOS_MemIntegrityCheck**: checks the integrity of the specified memory pool. It is valid only when **LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK** is enabled.|
| Adding discontiguous memory regions| **LOS_MemRegionsAdd**: logically integrates multiple discontiguous memory regions into a unified memory pool. This parameter is valid only when **LOSCFG_MEM_MUL_REGIONS** is enabled. If the memory pool pointer **pool** is empty, initialize the first of the multiple memory regions in the memory pool and insert other memory regions as free nodes. If **pool** is not empty, insert the multiple memory regions into the specified memory pool as free nodes.|
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> - The dynamic memory module manages memory through control block structures, which consume extra memory. Therefore, the actual memory space available to users is less than the value of **OS_SYS_MEM_SIZE**.
>
> - The **LOS_MemAllocAlign** and **LOS_MemMallocAlign** APIs consume extra memory for memory alignment, which may cause memory loss. When the memory used for alignment is freed up, the lost memory will be reclaimed.
>
> - The discontiguous memory regions passed by the **LosMemRegion** array to the **LOS_MemRegionsAdd** API must be sorted in ascending order by memory start address in memory regions, and the memory regions cannot overlap.
#### How to Develop
The typical development process of dynamic memory is as follows:
1. Call **LOS_MemInit** to initialize a memory pool.
After a memory pool is initialized, a memory pool control header and end node will be generated, and the remaining memory is marked as free nodes. The end node is the last node in the memory pool, and its size is **0**.
2. Call **LOS_MemAlloc** to allocate dynamic memory of any size.
The system checks whether the dynamic memory pool has free memory blocks greater than the requested size. If yes, the system allocates a memory block and returns the pointer to the memory block. If no, the system returns NULL. If the memory block allocated is greater than the requested size, the system splits the memory block and inserts the remaining memory block to the free list.
3. Call **LOS_MemFree** to release dynamic memory.
The released memory block can be reused. When **LOS_MemFree** is called, the memory block will be reclaimed and marked as free nodes. When memory blocks are reclaimed, adjacent free nodes are automatically merged.
#### Development Example
This example implements the following:
1. Initialize a dynamic memory pool.
2. Allocate a memory block from the dynamic memory pool.
3. Store a piece of data in the memory block.
4. Print the data in the memory block.
5. Release the memory block.
The sample code is as follows:
```
#include "los_memory.h"
#define TEST_POOL_SIZE (2*1024)
__attribute__((aligned(4))) UINT8 g_testPool[TEST_POOL_SIZE];
VOID Example_DynMem(VOID)
{
UINT32 *mem = NULL;
UINT32 ret;
/* Initialize the memory pool. */
ret = LOS_MemInit(g_testPool, TEST_POOL_SIZE);
if (LOS_OK == ret) {
printf("Mem init success!\n");
} else {
printf("Mem init failed!\n");
return;
}
/* Allocate memory. */
mem = (UINT32 *)LOS_MemAlloc(g_testPool, 4);
if (NULL == mem) {
printf("Mem alloc failed!\n");
return;
}
printf("Mem alloc success!\n");
/* Assign a value. */
*mem = 828;
printf("*mem = %d\n", *mem);
/ Release the memory. */
ret = LOS_MemFree(g_testPool, mem);
if (LOS_OK == ret) {
printf("Mem free success!\n");
} else {
printf("Mem free failed!\n");
}
return;
}
```
#### Verification
The output is as follows:
```
Mem init success!
Mem alloc success!
*mem = 828
Mem free success!
```
# Basic Kernel
- **[Interrupt Management](kernel-mini-basic-interrupt.md)**
- **[Task Management](kernel-mini-basic-task.md)**
- **[Memory Management](kernel-mini-basic-memory.md)**
- **[Kernel Communication Mechanisms](kernel-mini-basic-ipc.md)**
- **[Time Management](kernel-basic-mini-time.md)**
- **[Software Timer](kernel-mini-basic-soft.md)**
# Kernel Debugging
- **[Memory Debugging](kernel-mini-memory-debug.md)**
- **[Exception Debugging](kernel-mini-memory-exception.md)**
- **[Trace](kernel-mini-memory-trace.md)**
- **[LMS](kernel-mini-memory-lms.md)**
# FAT
## Basic Concepts
File Allocation Table (FAT) is a file system developed for personal computers. It consists of the DOS Boot Record (DBR) region, FAT region, and Data region. Each entry in the FAT region records information about the corresponding cluster in the storage device. The cluster information includes whether the cluster is used, number of the next cluster of the file, whether the file ends with the cluster.
The FAT file system supports multiple formats, such as FAT12, FAT16, and FAT32. The numbers 12, 16, and 32 indicate the number of bits per cluster within the FAT, respectively. The FAT file system supports multiple media, especially removable media (such as USB flash drives, SD cards, and removable hard drives). The FAT file system ensures good compatibility between embedded devices and desktop systems (such as Windows and Linux) and facilitates file management.
The OpenHarmony kernel supports FAT12, FAT16, and FAT32 file systems. These file systems require a tiny amount of code to implement, use less resources, support a variety of physical media, and are tailorable and compatible with Windows and Linux systems. They also support identification of multiple devices and partitions. The kernel supports multiple partitions on hard drives and allows creation of the FAT file system on the primary partition and logical partition.
## Development Guidelines
### Driver Adaptation
The use of the FAT file system requires support from the underlying MultiMedia Card (MMC) drivers. To run FatFS on a board with an MMC storage device, you must:
1. Implement the **disk_status**, **disk_initialize**, **disk_read**, **disk_write**, and **disk_ioctl** APIs to adapt to the embedded MMC (eMMC) drivers on the board.
2. Add the **fs_config.h** file with information such as **FS_MAX_SS** (maximum sector size of the storage device) and **FF_VOLUME_STRS** (partition names) configured.
The following is an example:
```
#define FF_VOLUME_STRS "system", "inner", "update", "user"
#define FS_MAX_SS 512
#define FAT_MAX_OPEN_FILES 50
```
### How to Develop
> ![](public_sys-resources/icon-note.gif) **NOTE**<br>
>
> Note the following when managing FatFS files and directories:
> - A file cannot exceed 4 GB.
> - **FAT\_MAX\_OPEN\_FILES** specifies the maximum number files you can open at a time, and **FAT\_MAX\_OPEN\_DIRS** specifies the maximum number of folders you can open at a time.
> - Root directory management is not supported. File and directory names start with the partition name. For example, **user/testfile** indicates the file or directory **testfile** in the **user** partition.
> - To open a file multiple times, use **O_RDONLY** (read-only mode). **O_RDWR** or **O_WRONLY** (writable mode) can open a file only once.
> - The read and write pointers are not separated. If a file is open in **O_APPEND** mode, the read pointer is also at the end of the file. If you want to read the file from the beginning, you must manually set the position of the read pointer.
> - File and directory permission management is not supported.
> - The **stat** and **fstat** APIs do not support query of the modification time, creation time, and last access time. The Microsoft FAT protocol does not support time before A.D. 1980.
>
> Note the following when mounting and unmounting FatFS partitions:
> - Partitions can be mounted with the read-only attribute. When the input parameter of the **mount** function is **MS_RDONLY**, all APIs with the write attribute, such as **write**, **mkdir**, **unlink**, and **open** with **non-O_RDONLY** attributes, will be rejected.
> - You can use the **MS_REMOUNT** flag with **mount** to modify the permission for a mounted partition.
> - Before unmounting a partition, ensure that all directories and files in the partition are closed.
> - You can use **umount2** with the **MNT_FORCE** parameter to forcibly close all files and folders and unmount the partition. However, this may cause data loss. Therefore, exercise caution when running **umount2**.
>
> The FAT file system supports re-partitioning and formatting of storage devices using **fatfs_fdisk** and **fatfs_format**.
> - If a partition is mounted before being formatted using **fatfs_format**, you must close all directories and files in the partition and unmount the partition first.
> - Before calling **fatfs_fdisk**, ensure that all partitions in the device are unmounted.
> - Using **fatfs_fdisk** and **fatfs_format** may cause data loss. Exercise caution when using them.
## Development Example
### Example Description
This example implements the following:
1. Create the **user/test** directory.
2. Create the **file.txt** file in the **user/test** directory.
3. Write **Hello OpenHarmony!** at the beginning of the file.
4. Save the file to a device.
5. Set the offset to the start position of the file.
6. Read the file.
7. Close the file.
8. Delete the file.
9. Delete the directory.
### Sample Code
**Prerequisites**
The MMC device partition is mounted to the **user** directory.
The sample code is as follows:
```
#include <stdio.h>
#include <string.h>
#include "sys/stat.h"
#include "fcntl.h"
#include "unistd.h"
#define LOS_OK 0
#define LOS_NOK -1
int FatfsTest(void)
{
int ret;
int fd = -1;
ssize_t len;
off_t off;
char dirName[20] = "user/test";
char fileName[20] = "user/test/file.txt";
char writeBuf[20] = "Hello OpenHarmony!";
char readBuf[20] = {0};
/* Create the user/test directory. */
ret = mkdir(dirName, 0777);
if (ret != LOS_OK) {
printf("mkdir failed.\n");
return LOS_NOK;
}
/* Create a readable and writable file named file.txt in the user/test/ directory. */
fd = open(fileName, O_RDWR | O_CREAT, 0777);
if (fd < 0) {
printf("open file failed.\n");
return LOS_NOK;
}
/* Write the content from writeBuf to the file. */
len = write(fd, writeBuf, strlen(writeBuf));
if (len != strlen(writeBuf)) {
printf("write file failed.\n");
return LOS_NOK;
}
/* Save the file to a storage device. */
ret = fsync(fd);
if (ret != LOS_OK) {
printf("fsync failed.\n");
return LOS_NOK;
}
/* Move the read/write pointer to the beginning of the file. */
off = lseek(fd, 0, SEEK_SET);
if (off != 0) {
printf("lseek failed.\n");
return LOS_NOK;
}
/* Read the file content with the length of readBuf to readBuf. */
len = read(fd, readBuf, sizeof(readBuf));
if (len != strlen(writeBuf)) {
printf("read file failed.\n");
return LOS_NOK;
}
printf("%s\n", readBuf);
/* Close the file. */
ret = close(fd);
if (ret != LOS_OK) {
printf("close failed.\n");
return LOS_NOK;
}
/* Delete the file file.txt from the user/test directory. */
ret = unlink(fileName);
if (ret != LOS_OK) {
printf("unlink failed.\n");
return LOS_NOK;
}
/* Delete the user/test directory. */
ret = rmdir(dirName);
if (ret != LOS_OK) {
printf("rmdir failed.\n");
return LOS_NOK;
}
return LOS_OK;
}
```
### Verification
The development is successful if the return result is as follows:
```
Hello OpenHarmony!
```
# LittleFS
## Basic Concepts
LittleFS is a small file system designed for flash. By combining the log-structured file system and the copy-on-write (COW) file system, LittleFS stores metadata in log structure and data in the COW structure. This special storage empowers LittleFS high power-loss resilience. LittleFS uses the statistical wear leveling algorithm when allocating COW data blocks, effectively prolonging the service life of flash devices. LittleFS is designed for small-sized devices with limited resources, such as ROM and RAM. All RAM resources are allocated through a buffer with the fixed size (configurable). That is, the RAM usage does not grow with the file system.
LittleFS is a good choice when you look for a flash file system that is power-cut resilient and has wear leveling support on a small device with limited resources.
## Development Guidelines
When porting LittleFS to a new hardware device, you need to declare **lfs_config**:
```
const struct lfs_config cfg = {
// block device operations
.read = user_provided_block_device_read,
.prog = user_provided_block_device_prog,
.erase = user_provided_block_device_erase,
.sync = user_provided_block_device_sync,
// block device configuration
.read_size = 16,
.prog_size = 16,
.block_size = 4096,
.block_count = 128,
.cache_size = 16,
.lookahead_size = 16,
.block_cycles = 500,
};
```
**.read**, **.prog**, **.erase**, and **.sync** correspond to the read, write, erase, and synchronization APIs at the bottom layer of the hardware platform, respectively.
**read_size** indicates the number of bytes read each time. You can set it to a value greater than the physical read unit to improve performance. This value determines the size of the read cache. However, if the value is too large, more memory is consumed.
**prog_size** indicates the number of bytes written each time. You can set it to a value greater than the physical write unit to improve performance. This value determines the size of the write cache and must be an integral multiple of **read_size**. However, if the value is too large, more memory is consumed.
**block_size**: indicates the number of bytes in each erase block. The value can be greater than that of the physical erase unit. However, a smaller value is recommended because each file occupies at least one block. The value must be an integral multiple of **prog_size**.
**block_count** indicates the number of blocks that can be erased, which depends on the capacity of the block device and the size of the block to be erased (**block_size**).
## Sample Code
The sample code is as follows:
```
#include "lfs.h"
#include "stdio.h"
lfs_t lfs;
lfs_file_t file;
const struct lfs_config cfg = {
// block device operations
.read = user_provided_block_device_read,
.prog = user_provided_block_device_prog,
.erase = user_provided_block_device_erase,
.sync = user_provided_block_device_sync,
// block device configuration
.read_size = 16,
.prog_size = 16,
.block_size = 4096,
.block_count = 128,
.cache_size = 16,
.lookahead_size = 16,
.block_cycles = 500,
};
int main(void) {
// mount the filesystem
int err = lfs_mount(&lfs, &cfg);
// reformat if we can't mount the filesystem
// this should only happen on the first boot
if (err) {
lfs_format(&lfs, &cfg);
lfs_mount(&lfs, &cfg);
}
// read current count
uint32_t boot_count = 0;
lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));
// update boot count
boot_count += 1;
lfs_file_rewind(&lfs, &file);
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
// remember the storage is not updated until the file is closed successfully
lfs_file_close(&lfs, &file);
// release any resources we were using
lfs_unmount(&lfs);
// print the boot count
printf("boot_count: %d\n", boot_count);
}
```
**Verification**
The development is successful if the return result is as follows:
```
Say hello 1 times.
```
# Extended Components
- **[C++ Support](kernel-mini-extend-support.md)**
- **[CPUP](kernel-mini-extend-cpup.md)**
- **[Dynamic Loading](kernel-mini-extend-dynamic-loading.md)**
- **[File System](kernel-mini-extend-file.md)**
# Memory Corruption Check
## Basic Concepts
As an optional function of the kernel, memory corruption check is used to check the integrity of a dynamic memory pool. This mechanism can detect memory corruption errors in the memory pool in a timely manner and provide alerts. It helps reduce problem locating costs and increase troubleshooting efficiency.
## Function Configuration
**LOSCFG\_BASE\_MEM\_NODE\_INTEGRITY\_CHECK**: specifies the setting of the memory corruption check. This function is disabled by default. To enable the function, set this macro to **1** in **target\_config.h**.
1. If this macro is enabled, the memory pool integrity will be checked in real time upon each memory allocation.
2. If this macro is not enabled, you can call **LOS\_MemIntegrityCheck** to check the memory pool integrity when required. Using **LOS\_MemIntegrityCheck** does not affect the system performance. In addition, the check accuracy decreases because the node header does not contain the magic number \(which is available only when **LOSCFG\_BASE\_MEM\_NODE\_INTEGRITY\_CHECK** is enabled\).
This check only detects the corrupted memory node and provides information about the previous node \(because memory is contiguous, a node is most likely corrupted by the previous node\). To further determine the location where the previous node is requested, you need to enable the memory leak check and use LRs to locate the fault.
>![](../public_sys-resources/icon-caution.gif) **CAUTION:**
>If memory corruption check is enabled, a magic number is added to the node header, which increases the size of the node header. The real-time integrity check has a great impact on the performance. In performance-sensitive scenarios, you are advised to disable this function and use **LOS\_MemIntegrityCheck** to check the memory pool integrity.
## Development Guidelines
### How to Develop
Check for memory corruption by calling **LOS\_MemIntegrityCheck**. If no memory corruption occurs, **0** is returned and no log is output. If memory corruption occurs, related log is output. For details, see the output of the following example.
### Development Example
This example implements the following:
1. Request two physically adjacent memory blocks.
2. Call **memset** to construct an out-of-bounds access and overwrites the first four bytes of the next node.
3. Call **LOS\_MemIntegrityCheck** to check whether memory corruption occurs.
### Sample Code
The sample code is as follows:
```
#include <stdio.h>
#include <string.h>
#include "los_memory.h"
#include "los_config.h"
void MemIntegrityTest(void)
{
/* Request two physically adjacent memory blocks.*/
void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
/* Construct an out-of-bounds access to cause memory corruption. The memory block of the first node is 8 bytes. Clearing 12 bytes overwrites the header of the second memory node. */
memset(ptr1, 0, 8 + 4);
LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR);
}
```
### Verification
The log is as follows:
```
[ERR][OsMemMagicCheckPrint], 2028, memory check error!
memory used but magic num wrong, magic num = 0x00000000 /* Error information, indicating that the first four bytes, that is, the magic number, of the next node are corrupted.*/
broken node head: 0x20003af0 0x00000000 0x80000020, prev node head: 0x20002ad4 0xabcddcba 0x80000020
/* Key information about the corrupted node and its previous node, including the address of the previous node, magic number of the node, and sizeAndFlag of the node. In this example, the magic number of the corrupted node is cleared. */
broken node head LR info: /* The node LR information can be output only after the memory leak check is enabled.*/
LR[0]:0x0800414e
LR[1]:0x08000cc2
LR[2]:0x00000000
pre node head LR info: /* Based on the LR information, you can find where the previous node is requested in the assembly file and then perform further analysis.*/
LR[0]:0x08004144
LR[1]:0x08000cc2
LR[2]:0x00000000
[ERR]Memory interity check error, cur node: 0x20003b10, pre node: 0x20003af0 /* Addresses of the corrupted node and its previous node*/
```
# Memory Leak Check
## Basic Concepts
As an optional function of the kernel, memory leak check is used to locate dynamic memory leak problems. After this function is enabled, the dynamic memory automatically records the link registers \(LRs\) used when memory is allocated. If a memory leak occurs, the recorded information helps locate the memory allocated for further analysis.
## Function Configuration
1. **LOSCFG\_MEM\_LEAKCHECK**: specifies the setting of the memory leak check. This function is disabled by default. To enable the function, set this macro to **1** in **target\_config.h**.
2. **LOSCFG\_MEM\_RECORD\_LR\_CNT**: number of LRs recorded. The default value is **3**. Each LR consumes the memory of **sizeof\(void \*\)** bytes.
3. **LOSCFG\_MEM\_OMIT\_LR\_CNT**: number of ignored LRs. The default value is **4**, which indicates that LRs are recorded from the time when **LOS\_MemAlloc** is called. You can change the value based on actual requirements. This macro is configured because:
- **LOS\_MemAlloc** is also called internally.
- **LOS\_MemAlloc** may be encapsulated externally.
- The number of LRs configured by **LOSCFG\_MEM\_RECORD\_LR\_CNT** is limited.
Correctly setting this macro can ignore invalid LRs and reduce memory consumption.
## Development Guidelines
### How to Develop
Memory leak check provides a method to check for memory leak in key code logic. If this function is enabled, LR information is recorded each time when memory is allocated. When **LOS\_MemUsedNodeShow** is called before and after the code snippet is checked, information about all nodes that have been used in the specified memory pool is printed. You can compare the node information. The newly added node information indicates the node where the memory leak may occur. You can locate the code based on the LR and further check whether a memory leak occurs.
The node information output by calling **LOS\_MemUsedNodeShow** is in the following format: Each line contains information about a node. The first column indicates the node address, based on which you can obtain complete node information using a tool such as a GNU Debugger \(GDB\). The second column indicates the node size, which is equal to the node header size plus the data field size. Columns 3 to 5 list the LR addresses. You can determine the specific memory location of the node based on the LR addresses and the assembly file.
```
node size LR[0] LR[1] LR[2]
0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002
0x10017848: 0xe0 0x9b02c24e 0x9b02c246 0x9b008ef0
0x10017928: 0x50 0x9b008ed0 0x9b068902 0x9b0687c4
0x10017978: 0x24 0x9b008ed0 0x9b068924 0x9b0687c4
0x1001799c: 0x30 0x9b02c24e 0x9b02c246 0x9b008ef0
0x100179cc: 0x5c 0x9b02c24e 0x9b02c246 0x9b008ef0
```
>![](../public_sys-resources/icon-caution.gif) **CAUTION**<br/>
>Enabling memory leak check affects memory application performance. LR addresses will be recorded for each memory node, increasing memory overhead.
### Development Example
This example implements the following:
1. Call **LOS\_MemUsedNodeShow** to print information about all nodes.
2. Simulate a memory leak by requesting memory without releasing it.
3. Call **LOS\_MemUsedNodeShow** to print information about all nodes.
4. Compare the logs to obtain information about the node where a memory leak occurred.
5. Locate the code based on the LR address.
### Sample Code
The sample code is as follows:
```
#include <stdio.h>
#include <string.h>
#include "los_memory.h"
#include "los_config.h"
void MemLeakTest(void)
{
LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR);
void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR);
}
```
### Verification
The log is as follows:
```
node size LR[0] LR[1] LR[2]
0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc
0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc
0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e
0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a
0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220
node size LR[0] LR[1] LR[2]
0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc
0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc
0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e
0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a
0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220
0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6
0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000
```
The difference between the two logs is as follows. The following memory nodes are suspected to have blocks with a memory leak.
```
0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6
0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000
```
The following is part of the assembly file:
```
MemLeakTest:
0x80041d4: 0xb510 PUSH {R4, LR}
0x80041d6: 0x4ca8 LDR.N R4, [PC, #0x2a0] ; g_memStart
0x80041d8: 0x0020 MOVS R0, R4
0x80041da: 0xf7fd 0xf93e BL LOS_MemUsedNodeShow ; 0x800145a
0x80041de: 0x2108 MOVS R1, #8
0x80041e0: 0x0020 MOVS R0, R4
0x80041e2: 0xf7fd 0xfbd9 BL LOS_MemAlloc ; 0x8001998
0x80041e6: 0x2108 MOVS R1, #8
0x80041e8: 0x0020 MOVS R0, R4
0x80041ea: 0xf7fd 0xfbd5 BL LOS_MemAlloc ; 0x8001998
0x80041ee: 0x0020 MOVS R0, R4
0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a
0x80041f4: 0xbd10 POP {R4, PC}
0x80041f6: 0x0000 MOVS R0, R0
```
The memory node addressed by **0x080041ee** is not released after being requested in **MemLeakTest**.
# Memory Information Statistics
## Basic Concepts
Memory information includes the memory pool size, memory usage, remaining memory size, maximum free memory, memory waterline, number of memory nodes, and fragmentation rate.
- Memory waterline: indicates the maximum memory used in a memory pool. The waterline value is updated upon each memory allocation and release. The memory pool size can be optimized based on this value.
- Fragmentation rate: indicates the fragmentation degree of the memory pool. If the fragmentation rate is high, there are a large number of free memory blocks in the memory pool but each block is small. You can use the following formula to calculate the fragmentation rate:
Fragmentation rate = 100 – 100 x Maximum free memory block size/Remaining memory size
- Other parameters: You can call APIs \(described in [Memory Management](kernel-mini-basic-memory-basic.md)\) to scan node information in the memory pool and collect statistics.
## Function Configuration
**LOSCFG\_MEM\_WATERLINE**: specifies the setting of the memory information statistics function. This function is enabled by default. To disable the function, set this macro to **0** in **target\_config.h**. If you want to obtain the memory waterline, you must enable this macro.
## Development Guidelines
### How to Develop
Key structure:
```
typedef struct {
UINT32 totalUsedSize; // Memory usage of the memory pool
UINT32 totalFreeSize; // Remaining memory in the memory pool
UINT32 maxFreeNodeSize; // Maximum size of the free memory block in the memory pool
UINT32 usedNodeNum; // Number of non-free memory blocks in the memory pool
UINT32 freeNodeNum; // Number of free memory blocks in the memory pool
#if (LOSCFG_MEM_WATERLINE == 1) // This macro is enabled by default. To disable it, set it to 0 in target_config.h.
UINT32 usageWaterLine; // Waterline of the memory pool
#endif
} LOS_MEM_POOL_STATUS;
```
- To obtain the memory waterline, call **LOS\_MemInfoGet**. The first parameter in the API is the start address of the memory pool, and the second parameter is the handle of the **LOS\_MEM\_POOL\_STATUS** type. The **usageWaterLine** field indicates the waterline.
- To calculate the memory fragmentation rate, call **LOS\_MemInfoGet** to obtain the remaining memory size and the maximum free memory block size in the memory pool, and then calculate the fragmentation rate of the dynamic memory pool as follows:
Fragmentation rate = 100 – 100 x Maximum free memory block size/Remaining memory size
### Development Example
This example implements the following:
1. Create a monitoring task to obtain information about the memory pool.
2. Call **LOS\_MemInfoGet** to obtain the basic information about the memory pool.
3. Calculate the memory usage and fragmentation rate.
### Sample Code
The sample code is as follows:
```
#include <stdio.h>
#include <string.h>
#include "los_task.h"
#include "los_memory.h"
#include "los_config.h"
void MemInfoTaskFunc(void)
{
LOS_MEM_POOL_STATUS poolStatus = {0};
/* pool is the memory address of the information to be collected. OS_SYS_MEM_ADDR is used as an example.*/
void *pool = OS_SYS_MEM_ADDR;
LOS_MemInfoGet(pool, &poolStatus);
/* Calculate the fragmentation rate of the memory pool. */
unsigned char fragment = 100 - poolStatus.maxFreeNodeSize * 100 / poolStatus.totalFreeSize;
/* Calculate the memory usage of the memory pool. */
unsigned char usage = LOS_MemTotalUsedGet(pool) * 100 / LOS_MemPoolSizeGet(pool);
printf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize,
poolStatus.totalFreeSize, poolStatus.usageWaterLine);
}
int MemTest(void)
{
unsigned int ret;
unsigned int taskID;
TSK_INIT_PARAM_S taskStatus = {0};
taskStatus.pfnTaskEntry = (TSK_ENTRY_FUNC)MemInfoTaskFunc;
taskStatus.uwStackSize = 0x1000;
taskStatus.pcName = "memInfo";
taskStatus.usTaskPrio = 10;
ret = LOS_TaskCreate(&taskID, &taskStatus);
if (ret != LOS_OK) {
printf("task create failed\n");
return -1;
}
return 0;
}
```
### Verification
The result is as follows:
```
usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414
```
# Memory Debugging # Memory Debugging
The purpose of memory debugging is to locate problems related to dynamic memory. The kernel provides a variety of memory debugging methods. Dynamic memory pool statistics helps you learn the memory pool waterline and fragmentation rate. Memory leak check helps you accurately locate the code where memory leak occurs and analyze the memory usage of each module. Memory corruption check helps you locate memory corruptions. The purpose of memory debugging is to locate problems related to dynamic memory. The kernel provides a variety of memory debugging methods. Dynamic memory pool statistics helps you learn the memory pool waterline and fragmentation rate. Memory leak check helps you accurately locate the code where memory leak occurs and analyze the memory usage of each module. Memory corruption check helps you locate memory corruptions.
- **[Memory Information Statistics](kernel-mini-memory-debug-mes.md)**
- **[Memory Leak Check](kernel-mini-memory-debug-det.md)** ## Memory Information Statistics
### Basic Concepts
Memory information includes the memory pool size, memory usage, remaining memory size, maximum free memory, memory waterline, number of memory nodes, and fragmentation rate.
- Memory waterline: indicates the maximum memory used in a memory pool. The waterline value is updated upon each memory allocation and release. The memory pool size can be optimized based on this value.
- Fragmentation rate: indicates the fragmentation degree of the memory pool. If the fragmentation rate is high, there are a large number of free memory blocks in the memory pool but each block is small. You can use the following formula to calculate the fragmentation rate:<br>Fragmentation rate = 100 – 100 x Maximum free memory block size/Remaining memory size
- Other parameters: You can call APIs described in [Memory Management](../kernel/kernel-mini-basic-memory.md) to scan node information in the memory pool and collect statistics.
### Function Configuration
**LOSCFG_MEM_WATERLINE**: specifies the setting of the memory information statistics function. This function is enabled by default. To disable the function, set this macro to **0** in **target_config.h**. If you want to obtain the memory waterline, you must enable this macro.
### Development Guidelines
#### How to Develop
Key structure:
```
typedef struct {
UINT32 totalUsedSize; // Memory usage of the memory pool.
UINT32 totalFreeSize; // Remaining size of the memory pool.
UINT32 maxFreeNodeSize; // Maximum size of the free memory block in the memory pool.
UINT32 usedNodeNum; // Number of non-free memory blocks in the memory pool.
UINT32 freeNodeNum; // Number of free memory blocks in the memory pool.
#if (LOSCFG_MEM_WATERLINE == 1) //The function is enabled by default. To disable it, set this macro to 0 in target_config.h.
UINT32 usageWaterLine; // Waterline of the memory pool.
#endif
} LOS_MEM_POOL_STATUS;
```
- To obtain the memory waterline, call **LOS_MemInfoGet**. The first parameter in the API is the start address of the memory pool, and the second parameter is the handle of the **LOS_MEM_POOL_STATUS** type. The **usageWaterLine** field indicates the waterline.
- To calculate the memory fragmentation rate, call **LOS_MemInfoGet** to obtain the remaining memory size and the maximum free memory block size in the memory pool, and then calculate the fragmentation rate of the dynamic memory pool as follows:<br>Fragmentation rate = 100 – 100 x Maximum free memory block size/Remaining memory size
#### Development Example
This example implements the following:
1. Create a monitoring task to obtain information about the memory pool.
2. Calls **LOS_MemInfoGet** to obtain the basic information about the memory pool.
3. Calculate the memory usage and fragmentation rate.
#### Sample Code
The sample code is as follows:
```
#include <stdio.h>
#include <string.h>
#include "los_task.h"
#include "los_memory.h"
#include "los_config.h"
void MemInfoTaskFunc(void)
{
LOS_MEM_POOL_STATUS poolStatus = {0};
/* pool is the memory address of the information to be collected. OS_SYS_MEM_ADDR is used as an example. */
void *pool = OS_SYS_MEM_ADDR;
LOS_MemInfoGet(pool, &poolStatus);
/* Calculate the fragmentation rate of the memory pool. */
unsigned char fragment = 100 - poolStatus.maxFreeNodeSize * 100 / poolStatus.totalFreeSize;
/* Calculate the memory usage of the memory pool. */
unsigned char usage = LOS_MemTotalUsedGet(pool) * 100 / LOS_MemPoolSizeGet(pool);
printf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize,
poolStatus.totalFreeSize, poolStatus.usageWaterLine);
}
int MemTest(void)
{
unsigned int ret;
unsigned int taskID;
TSK_INIT_PARAM_S taskStatus = {0};
taskStatus.pfnTaskEntry = (TSK_ENTRY_FUNC)MemInfoTaskFunc;
taskStatus.uwStackSize = 0x1000;
taskStatus.pcName = "memInfo";
taskStatus.usTaskPrio = 10;
ret = LOS_TaskCreate(&taskID, &taskStatus);
if (ret != LOS_OK) {
printf("task create failed\n");
return -1;
}
return 0;
}
```
#### Verification
The result is as follows:
```
usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414
```
## Memory Leak Check
### Basic Concepts
As an optional function of the kernel, memory leak check is used to locate dynamic memory leak problems. After this function is enabled, the dynamic memory automatically records the link registers (LRs) used when memory is allocated. If a memory leak occurs, the recorded information helps locate the memory allocated for further analysis.
### Function Configuration
1. **LOSCFG_MEM_LEAKCHECK**: specifies the setting of the memory leak check. This function is disabled by default. To enable the function, set this macro to **1** in **target_config.h**.
2. **LOSCFG_MEM_RECORD_LR_CNT**: specifies the number of LRs recorded. The default value is **3**. Each LR consumes the memory of **sizeof(void\*)** bytes.
3. **LOSCFG_MEM_OMIT_LR_CNT**: specifies the number of ignored LRs. The default value is **4**, which indicates that LRs are recorded from the time when **LOS_MemAlloc** is called. You can change the value based on actual requirements. This macro is configured because:
- **LOS_MemAlloc** is also called internally.
- **LOS_MemAlloc** may be encapsulated externally.
- The number of LRs configured by **LOSCFG_MEM_RECORD_LR_CNT** is limited.
Correctly setting this macro can ignore invalid LRs and reduce memory consumption.
### Development Guidelines
#### How to Develop
Memory leak check provides a method to check for memory leak in key code logic. If this function is enabled, LR information is recorded each time when memory is allocated. When **LOS_MemUsedNodeShow** is called before and after the code snippet is checked, information about all nodes that have been used in the specified memory pool is printed. You can compare the node information. The newly added node information indicates the node where the memory leak may occur. You can locate the code based on the LR and further check whether a memory leak occurs.
The node information output by calling **LOS_MemUsedNodeShow** is in the following format: <br>Each line contains information about a node. The first column indicates the node address, based on which you can obtain complete node information using a tool such as a GNU Debugger (GDB). The second column indicates the node size, which is equal to the node header size plus the data field size. Columns 3 to 5 list the LR addresses. You can determine the specific memory location of the node based on the LR addresses and the assembly file.
```
node size LR[0] LR[1] LR[2]
0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002
0x10017848: 0xe0 0x9b02c24e 0x9b02c246 0x9b008ef0
0x10017928: 0x50 0x9b008ed0 0x9b068902 0x9b0687c4
0x10017978: 0x24 0x9b008ed0 0x9b068924 0x9b0687c4
0x1001799c: 0x30 0x9b02c24e 0x9b02c246 0x9b008ef0
0x100179cc: 0x5c 0x9b02c24e 0x9b02c246 0x9b008ef0
```
> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**<br/>
> Enabling memory leak check affects memory application performance. LR addresses will be recorded for each memory node, increasing memory overhead.
#### Development Example
This example implements the following:
1. Call **LOS_MemUsedNodeShow** to print information about all nodes.
2. Simulate a memory leak by requesting memory without releasing it.
3. Call **LOS_MemUsedNodeShow** to print information about all nodes.
4. Compare the logs to obtain information about the node where a memory leak occurred.
5. Locate the code based on the LR address.
#### Sample Code
The sample code is as follows:
```
#include <stdio.h>
#include <string.h>
#include "los_memory.h"
#include "los_config.h"
void MemLeakTest(void)
{
LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR);
void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR);
}
```
#### Verification
The log is as follows:
```
node size LR[0] LR[1] LR[2]
0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc
0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc
0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e
0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a
0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220
node size LR[0] LR[1] LR[2]
0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc
0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc
0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e
0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a
0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220
0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6
0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000
```
The difference between the two logs is as follows. The following memory nodes are suspected to have blocks with a memory leak.
```
0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6
0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000
```
The following is part of the assembly file:
```
MemLeakTest:
0x80041d4: 0xb510 PUSH {R4, LR}
0x80041d6: 0x4ca8 LDR.N R4, [PC, #0x2a0] ; g_memStart
0x80041d8: 0x0020 MOVS R0, R4
0x80041da: 0xf7fd 0xf93e BL LOS_MemUsedNodeShow ; 0x800145a
0x80041de: 0x2108 MOVS R1, #8
0x80041e0: 0x0020 MOVS R0, R4
0x80041e2: 0xf7fd 0xfbd9 BL LOS_MemAlloc ; 0x8001998
0x80041e6: 0x2108 MOVS R1, #8
0x80041e8: 0x0020 MOVS R0, R4
0x80041ea: 0xf7fd 0xfbd5 BL LOS_MemAlloc ; 0x8001998
0x80041ee: 0x0020 MOVS R0, R4
0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a
0x80041f4: 0xbd10 POP {R4, PC}
0x80041f6: 0x0000 MOVS R0, R0
```
The memory node addressed by **0x080041ee** is not released after being requested in **MemLeakTest**.
## Memory Corruption Check
### Basic Concepts
As an optional function of the kernel, memory corruption check is used to check the integrity of a dynamic memory pool. This mechanism can detect memory corruption errors in the memory pool in a timely manner and provide alerts. It helps reduce problem locating costs and increase troubleshooting efficiency.
### Function Configuration
**LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK**: specifies the setting of the memory corruption check. This function is disabled by default. To enable the function, set this macro to **1** in **target_config.h**.
1. If this macro is enabled, the memory pool integrity will be checked in real time upon each memory allocation.
2. If this macro is not enabled, you can call **LOS_MemIntegrityCheck** to check the memory pool integrity when required. Using **LOS_MemIntegrityCheck** does not affect the system performance. In addition, the check accuracy decreases because the node header does not contain the magic number (which is available only when **LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK** is enabled).
This check only detects the corrupted memory node and provides information about the previous node (because memory is contiguous, a node is most likely corrupted by the previous node). To further determine the location where the previous node is requested, you need to enable the memory leak check and use LRs to locate the fault.
> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**<br/>
> If memory corruption check is enabled, a magic number is added to the node header, which increases the size of the node header. The real-time integrity check has a great impact on the performance. In performance-sensitive scenarios, you are advised to disable this function and use **LOS_MemIntegrityCheck** to check the memory pool integrity.
### Development Guidelines
#### How to Develop
Check for memory corruption by calling **LOS_MemIntegrityCheck**. If no memory corruption occurs, **0** is returned and no log is output. If memory corruption occurs, the related log is output. For details, see the output of the following example.
#### Development Example
This example implements the following:
1. Request two physically adjacent memory blocks.
2. Use **memset** to construct an out-of-bounds access and overwrites the first four bytes of the next node.
3. Call **LOS_MemIntegrityCheck** to check whether memory corruption occurs.
#### Sample Code
The sample code is as follows:
```
#include <stdio.h>
#include <string.h>
#include "los_memory.h"
#include "los_config.h"
void MemIntegrityTest(void)
{
/* Request two physically adjacent memory blocks. */
void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8);
/* Construct an out-of-bounds access to cause memory corruption. The memory block of the first node is 8 bytes. Clearing 12 bytes overwrites the header of the second memory node. */
memset(ptr1, 0, 8 + 4);
LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR);
}
```
#### Verification
The log is as follows:
```
[ERR][OsMemMagicCheckPrint], 2028, memory check error!
memory used but magic num wrong, magic num = 0x00000000 /* Error information, indicating that the first four bytes, that is, the magic number, of the next node are corrupted. */
- **[Memory Corruption Check](kernel-mini-memory-debug-cet.md)** broken node head: 0x20003af0 0x00000000 0x80000020, prev node head: 0x20002ad4 0xabcddcba 0x80000020
/* Key information about the corrupted node and its previous node, including the address of the previous node, magic number of the node, and sizeAndFlag of the node. In this example, the magic number of the corrupted node is cleared. */
broken node head LR info: /* The node LR information can be output only after the memory leak check is enabled. */
LR[0]:0x0800414e
LR[1]:0x08000cc2
LR[2]:0x00000000
pre node head LR info: /* Based on the LR information, you can find where the previous node is requested in the assembly file and then perform further analysis. */
LR[0]:0x08004144
LR[1]:0x08000cc2
LR[2]:0x00000000
[ERR]Memory integrity check error, cur node: 0x20003b10, pre node: 0x20003af0 /* Addresses of the corrupted node and its previous node */
```
# Mini-System Kernel
- **[Kernel Overview](kernel-mini-overview.md)**
- **[Basic Kernel](kernel-mini-basic.md)**
- **[Extended Components](kernel-mini-extend.md)**
- **[Kernel Debugging](kernel-mini-debug.md)**
- **[Appendix](kernel-mini-app.md)**
# Basic Data Structure
- **[Doubly Linked List](kernel-small-apx-dll.md)**
- **[Bitwise Operation](kernel-small-apx-bitwise.md)**
# Appendix
- **[Basic Data Structure](kernel-small-apx-structure.md)**
- **[Standard Library](kernel-small-apx-library.md)**
# Memory Management
- **[Heap Memory Management](kernel-small-basic-memory-heap.md)**
- **[Physical Memory Management](kernel-small-basic-memory-physical.md)**
- **[Virtual Memory Management](kernel-small-basic-memory-virtual.md)**
- **[Virtual-to-Physical Mapping](kernel-small-basic-inner-reflect.md)**
# Process Management
- **[Process](kernel-small-basic-process-process.md)**
- **[Task](kernel-small-basic-process-thread.md)**
- **[Scheduler](kernel-small-basic-process-scheduler.md)**
# Kernel Communication Mechanisms
- **[Event](kernel-small-basic-trans-event.md)**
- **[Semaphore](kernel-small-basic-trans-semaphore.md)**
- **[Mutex](kernel-small-basic-trans-mutex.md)**
- **[Queue](kernel-small-basic-trans-queue.md)**
- **[RW Lock](kernel-small-basic-trans-rwlock.md)**
- **[Futex](kernel-small-basic-trans-user-mutex.md)**
- **[Signal](kernel-small-basic-trans-user-signal.md)**
# Basic Kernel
- **[Interrupt and Exception Handling](kernel-small-basic-interrupt.md)**
- **[Process Management](kernel-small-basic-process.md)**
- **[Memory Management](kernel-small-basic-memory.md)**
- **[Kernel Communication Mechanisms](kernel-small-basic-trans.md)**
- **[Time Management](kernel-small-basic-time.md)**
- **[Software Timer](kernel-small-basic-softtimer.md)**
- **[Atomic Operation](kernel-small-basic-atomic.md)**
# FAT
## Basic Concepts
File Allocation Table (FAT) is a file system developed for personal computers. It consists of the DOS Boot Record (DBR) region, FAT region, and Data region. Each entry in the FAT region records information about the corresponding cluster in the storage device. The cluster information includes whether the cluster is used, number of the next cluster of the file, whether the file ends with the cluster. The FAT file system supports multiple formats, such as FAT12, FAT16, and FAT32. The numbers 12, 16, and 32 indicate the number of bits per cluster within the FAT, and also restrict the maximum file size in the system. The FAT file system supports multiple media, especially removable media (such as USB flash drives, SD cards, and removable hard drives). The FAT file system ensures good compatibility between embedded devices and desktop systems (such as Windows and Linux) and facilitates file management.
The OpenHarmony kernel supports FAT12, FAT16, and FAT32 file systems. These file systems require a tiny amount of code to implement, use less resources, support a variety of physical media, and are tailorable and compatible with Windows and Linux systems. They also support identification of multiple devices and partitions. The kernel supports multiple partitions on hard drives and allows creation of the FAT file system on the primary partition and logical partition.
## Working Principles
This document does not include the FAT design and physical layout. You can find a lot of reference on the Internet.
The OpenHarmony LiteOS-A kernel uses block cache (Bcache) to improve FAT performance. When read and write operations are performed, Bcache caches the sectors close to the read and write sectors to reduce the number of I/Os and improve performance. The basic cache unit of Bcache is block. The size of each block is the same. By default, there are 28 blocks, and each block caches data of 64 sectors. When the Bcache dirty block rate (number of dirty sectors/total number of sectors) reaches the threshold, writeback is triggered and cached data is written back to disks. You can manually call **sync** and **fsync** to write data to disks if you want. Some FAT APIs (such as **close** and **umount**) may also trigger writeback operations. However, you are advised not to use them to trigger writeback.
## Development Guidelines
**How to Develop**
The development process involves mounting partitions, managing files and directories, and unmounting partitions.
The device name of the SD card or MMC is **mmcblk[x]p[y]**, and the file system type is **vfat**.
Example:
```
mount("/dev/mmcblk0p0", "/mnt", "vfat", 0, NULL);
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> - The size of a single FAT file cannot be greater than 4 GiB.
>
> - When there are two SD card slots, the first card inserted is card 0, and that inserted later is card 1.
>
> - When multi-partition is enabled and there are multiple partitions, the device node **/dev/mmcblk0** (primary device) registered by card 0 and **/dev/mmcblk0p0** (secondary device) are the same device. In this case, you cannot perform operations on the primary device.
>
> - Before removing an SD card, close the open files and directories and unmount the related nodes. Otherwise, SD card exceptions or memory leaks may occur.
>
> - Before performing the **format** operation, unmount the mount point.
>
> - After the Bcache feature takes effect, note the following:
> - When **MS_NOSYNC** is carried in the **mount** function, FAT does not proactively write the content in the cache back to the storage device. The FAT-related APIs **open**, **close**, **unlink**, **rename**, **mkdir**, **rmdir**, and **truncate** do not automatically perform the **sync** operation, which improves the operation speed. However, the upper layer must actively invoke the **sync** operation to synchronize data. Otherwise, data loss may occur.
>
> - Bcache provides scheduled writeback. After **LOSCFG_FS_FAT_CACHE_SYNC_THREAD** is enabled in **menuconfig**, the OpenHarmony kernel creates a scheduled task to write the Bcache data back to disks. By default, the kernel checks the dirty block rate in the Bcache every 5 seconds. If the dirty block rate exceeds 80%, the **sync** operation will be performed to write all dirty data in the Bcache to disks. You can call **LOS_SetSyncThreadPrio**, **LOS_SetSyncThreadInterval**, and **LOS_SetDirtyRatioThreshold** to set the task priority, flush interval, and dirty block rate threshold, respectively.
> - The cache has 28 blocks by default, and each block has 64 sectors.
# JFFS2
## Basic Concepts<a name="section11411110155919"></a>
Journalling Flash File System Version 2 \(JFFS2\) is a log-structured file system designed for Memory Technology Devices \(MTDs\).
JFFS2 is used on the NOR flash memory of the OpenHarmony. JFFS2 is readable and writable, supports data compression, provides crash/power failure protection, and supports wear leveling. There are many differences between flash memory and disk media. Running a disk file system on a flash memory device will cause performance and security problems. JFFS2 is a file system optimized for flash memory.
## Working Principles<a name="section23911025195913"></a>
This document does not include the physical layout of JFFS2 on storage devices and JFFS2 specifications. For details, see the [official JFFS2 specification document](https://sourceware.org/jffs2/).
The following describes several important mechanisms and features of JFFS2 that you may concern.
1. Mount mechanism and speed: According to the JFFS2 design, all files are divided into nodes of different sizes based on certain rules and stored on the flash memory device in sequence. In the mount process, all node information needs to be obtained and cached in the memory. Therefore, the mount speed is in linear proportion to the flash device capacity and the number of files. This is a native design issue of JFFS2. To increase the mount speed, you can select **Enable JFFS2 SUMMARY** during kernel compilation. If this option is selected, information required by the mount operation will be stored to the flash memory in advance. When the mount operation is performed, this information can be read and parsed quickly, ensuring relatively constant mount speed. However, this space-for-time practice consumes about 8% extra space.
2. Wear leveling: Due to the physical attributes of flash memory devices, read and write operations can be performed only on blocks of a specific size. To prevent certain blocks from being severely worn, wear leveling is used on written blocks in JFFS2 to ensure relatively balanced writes on all blocks. This prolongs the overall service life of the flash memory devices.
3. Garbage collection \(GC\) mechanism: When a deletion operation is performed in JFFS2, the physical memory is not released immediately. An independent GC thread performs GC operations such as space defragmentation and migration. However, GC in JFFS2 affects instantaneous read/write performance, like all GC mechanisms. In addition, JFFS2 reserves about three blocks in each partition for space defragmentation. The reserved space is invisible to users.
4. Compression mechanism: The underlying layer automatically decompresses or compresses the data read or written each time in JFFS2. The actual I/O size is different from the read or write size requested by the user. You cannot estimate whether the write operation will succeed or not based on the size of the written data and the remaining space of the flash memory.
5. Hard link mechanism: JFFS2 supports hard links. Multiple hard links of the same file occupy physical memory space of only one hard link. The physical space is released only when all hard links are deleted.
## Development Guidelines<a name="section179711119014"></a>
The development based on JFFS2 and NOR flash memory is similar to the development based on other file systems because the VFS shields the differences of specific file systems and the standard POSIX APIs are used as external APIs.
The raw NOR flash device has no place to centrally manage and record partition information. Therefore, you need to transfer the partition information by using other configuration methods \(using the **bootargs** parameter during image burning\), call the corresponding API in the code to add partitions, and then mount the partitions.
**Creating a JFFS2 Image**
Use the **mkfs.jffs2** tool to create an image. The default page size is 4 KiB, and the default **eraseblock** size is 64 KiB. Modify the parameter values to match your development.
```
./mkfs.jffs2 -d rootfs/ -o rootfs.jffs2
```
**Table 1** Command description \(run **mkfs.jffs2 --help** to view more details\)
<a name="table1925613541465"></a>
<table><thead align="left"><tr id="row325613545615"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p153851336772"><a name="p153851336772"></a><a name="p153851336772"></a>Command</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p43852366714"><a name="p43852366714"></a><a name="p43852366714"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row125715410619"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p20385103615715"><a name="p20385103615715"></a><a name="p20385103615715"></a>-s</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1338510362717"><a name="p1338510362717"></a><a name="p1338510362717"></a>Specifies the page size. If this parameter is not specified, the default value <strong id="b3814183173513"><a name="b3814183173513"></a><a name="b3814183173513"></a>4KiB</strong> is used.</p>
</td>
</tr>
<tr id="row787741814720"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p538673616710"><a name="p538673616710"></a><a name="p538673616710"></a>-e</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p6386123612719"><a name="p6386123612719"></a><a name="p6386123612719"></a>Specifies the <strong id="b56716452412"><a name="b56716452412"></a><a name="b56716452412"></a>eraseblock</strong> size. If this parameter is not specified, the default value <strong id="b17480133411354"><a name="b17480133411354"></a><a name="b17480133411354"></a>64KiB</strong> is used.</p>
</td>
</tr>
<tr id="row1160020211719"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p83861361079"><a name="p83861361079"></a><a name="p83861361079"></a>-p</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1491185544517"><a name="p1491185544517"></a><a name="p1491185544517"></a>Specifies the image size. 0xFF is filled at the end of the image file to make the file to the specified size. If the size is not specified, 0xFF is filled to a value aligned with <strong id="b6777155933718"><a name="b6777155933718"></a><a name="b6777155933718"></a>eraseblock</strong>.</p>
</td>
</tr>
<tr id="row151563245714"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p183864361579"><a name="p183864361579"></a><a name="p183864361579"></a>-d</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p238618361573"><a name="p238618361573"></a><a name="p238618361573"></a>Specifies the source directory of the file system image.</p>
</td>
</tr>
<tr id="row1323210319714"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p103867369710"><a name="p103867369710"></a><a name="p103867369710"></a>-o</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1938603617710"><a name="p1938603617710"></a><a name="p1938603617710"></a>Specifies the image name.</p>
</td>
</tr>
</tbody>
</table>
**Mounting a JFFS2 Partition**
Call **int mount\(const char \*source, const char \*target, const char \*filesystemtype, unsigned long mountflags, const void \*data\)** to mount the device node and mount point.
This function has the following parameters:
- **const char \*source** specifies the device node.
- **const char \*target** specifies the mount point.
- **const char \*filesystemtype** specifies the file system type.
- **unsigned long mountflags** specifies the mount flag, which is **0** by default.
- **const void \*data** specifies the data, which is **NULL** by default.
You can also run the **mount** command in **shell** to mount a JFFS2 partition. In this case, you do not need to specify the last two parameters.
Run the following command:
```
OHOS # mount /dev/spinorblk1 /jffs1 jffs2
```
If the following information is displayed, the JFFS2 partition is mounted:
```
OHOS # mount /dev/spinorblk1 /jffs1 jffs2
mount OK
```
Now, you can perform read and write operations on the NOR flash memory.
**Unmounting a JFFS2 Partition**
Call **int umount\(const char \*target\)** to unmount a partition. You only need to specify the correct mount point.
Run the following command:
```
OHOS # umount /jffs1
```
If the following information is displayed, the JFFS2 partition is unmounted:
```
OHOS # umount /jffs1
umount ok
```
# NFS
## Basic Concepts
Network File System (NFS) allows you to share files across hosts and OSs over a network. You can treat NFS as a file system service, which is equivalent to folder sharing in the Windows OS to some extent.
## Working Principles
The NFS of the OpenHarmony LiteOS-A kernel acts as an NFS client. The NFS client can mount the directory shared by a remote NFS server to the local machine and run the programs and shared files without occupying the storage space of the current system. To the local machine, the directory on the remote server is like its disk.
## Development Guidelines
1. Create an NFS server.
The following uses the Ubuntu OS as an example to describe how to configure an NFS server.
- Install the NFS server software.
Set the download source of the Ubuntu OS when the network connection is normal.
```
sudo apt-get install nfs-kernel-server
```
- Create a directory for mounting and assign full permissions for the directory.
```
mkdir -p /home/sqbin/nfs
sudo chmod 777 /home/sqbin/nfs
```
- Configure and start the NFS server.
Append the following line in the **/etc/exports** file:
```
/home/sqbin/nfs *(rw,no_root_squash,async)
```
**/home/sqbin/nfs** is the root directory shared by the NFS server.
Start the NFS server.
```
sudo /etc/init.d/nfs-kernel-server start
```
Restart the NFS server.
```
sudo /etc/init.d/nfs-kernel-server restart
```
2. Configure the board as an NFS client.
In this section, the NFS client is a device running the OpenHarmony kernel.
- Set the hardware connection.
Connect the OpenHarmony kernel device to the NFS server. Set their IP addresses in the same network segment. For example, set the IP address of the NFS server to **10.67.212.178/24** and the IP address of the OpenHarmony kernel device to
**10.67.212.3/24**. Note that this IP address is an intranet private IP address. Use the actual IP address.
You can run the **ifconfig** command to check the OpenHarmony kernel device's IP address.
- Start the network and ensure that the network between the board and NFS server is normal.
Start the Ethernet or another type of network, and then run **ping** to check whether the network connection to the server is normal.
```
OHOS # ping 10.67.212.178
[0]Reply from 10.67.212.178: time=1ms TTL=63
[1]Reply from 10.67.212.178: time=0ms TTL=63
[2]Reply from 10.67.212.178: time=1ms TTL=63
[3]Reply from 10.67.212.178: time=1ms TTL=63
--- 10.67.212.178 ping statistics ---
4 packets transmitted, 4 received, 0 loss
```
Initialize the NFS client.
```
OHOS # mkdir /nfs
OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000
```
If the following information is displayed, the NFS client is initialized.
```
OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000
Mount nfs on 10.67.212.178:/home/sqbin/nfs, uid:1011, gid:1000
Mount nfs finished.
```
This command mounts the **/home/sqbin/nfs** directory on the NFS server (IP address: 10.67.212.178) to the **/nfs** directory on the OpenHarmony kernel device.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
>
> This example assumes that the NFS server is available, that is, the **/home/sqbin/nfs** directory on the NFS server 10.67.212.178 is accessible.
>
> The **mount** command format is as follows:
>
> ```
> mount <SERVER_IP:SERVER_PATH> <CLIENT_PATH> nfs
> ```
>
> **SERVER_IP** indicates the IP address of the server; **SERVER_PATH** indicates the path of the shared directory on the NFS server; **CLIENT_PATH** indicates the NFS path on the local device; **nfs** indicates the path to which the remote shared directory is mounted on the local device. Replace the parameters as required.
>
> If you do not want to restrict the NFS access permission, set the permission of the NFS root directory to **777** on the Linux CLI.
>
> ```
> chmod -R 777 /home/sqbin/nfs
> ```
>
> The NFS client setting is complete, and the NFS file system is mounted.
3. Share files using NFS.
Create the **dir** directory on the NFS server. Run the **ls** command in the OpenHarmony kernel.
```
OHOS # ls /nfs
```
The following information is returned from the serial port:
```
OHOS # ls /nfs
Directory /nfs:
drwxr-xr-x 0 u:0 g:0 dir
```
The **dir** directory created on the NFS server has been synchronized to the **/nfs** directory on the client (OpenHarmony kernel system). Similarly, you can create files and directories on the client (OpenHarmony kernel system) and access them from the NFS server.
> ![](public_sys-resources/icon-note.gif) **NOTE**
>
> Currently, the NFS client supports some NFS v3 specifications. Therefore, the NFS client is not fully compatible with all types of NFS servers. You are advised to use the Linux NFS server to perform the development.
# procfs
## Basic Concepts
The proc filesystem (procfs) is a virtual file system that displays process or other system information in a file-like structure. It is more convenient to obtain system information in file operation mode than API calling mode.
## Working Principles
In the OpenHarmony kernel, procfs is automatically mounted to the **/proc** directory during startup. Only the kernel module can create file nodes to provide the query service.
## Development Guidelines
To create a procfs file, you need to use **ProcMkdir** to create a directory and use **CreateProcEntry** to create a file. The development of the file node function is to hook the read and write functions to the file created by **CreateProcEntry**. When the procfs file is read or written, the hooked functions will be called to implement custom functions.
### Development Example
The following describes how to create the **/proc/hello/world** file to implement the following functions:
1. Create a file in **/proc/hello/world**.
2. Read the file. When the file is read, "HelloWorld!" is returned.
3. Write the file and print the data written in the file.
```
#include "proc_fs.h"
static int TestRead(struct SeqBuf *buf, void *arg)
{
LosBufPrintf(buf, "Hello World! \n"); /* Print "Hello World!" to the buffer. The data in the buffer will be returned to the read result. */
return 0;
}
static int TestWrite(struct ProcFile *pf, const char *buffer, size_t buflen, loff_t *ppos)
{
if ((buffer == NULL) || (buflen <= 0)) {
return -EINVAL;
}
PRINTK("your input is: %s\n", buffer); /* Different from the read API, the write API prints the data only to the console. */
return buflen;
}
static const struct ProcFileOperations HELLO_WORLD_OPS = {
.read = TestRead,
.write = TestWrite,
};
void HelloWorldInit(void)
{
/* Create the hello directory. */
struct ProcDirEntry *dir = ProcMkdir("hello", NULL);
if (dir == NULL) {
PRINT_ERR("create dir failed!\n");
return;
}
/* Create the world file. */
struct ProcDirEntry *entry = CreateProcEntry("world", 0, dir);
if (entry == NULL) {
PRINT_ERR("create entry failed!\n");
return;
}
/* Hook the custom read and write APIs to the file. */
entry->procFileOps = &HELLO_WORLD_OPS;
}
```
**Verification**
After the OS startup, run the following commands in the shell:
```
OHOS # cat /proc/hello/world
OHOS # Hello World!
OHOS # echo "yo" > /proc/hello/world
OHOS # your input is: yo
```
# Ramfs
## Basic Concepts
Ramfs is a RAM-based file system whose size can be dynamically adjusted. Ramfs does not have a backing store. Directory entries and page caches are allocated when files are written into ramfs. However, data is not written back to any other storage medium. This means that data will be lost after a power outage.
## Working Principles
Ramfs stores all files in RAM, and read/write operations are performed in RAM. Ramfs is generally used to store temporary data or data that needs to be frequently modified, such as the **/tmp** and **/var** directories. Using ramfs reduces the read/write loss of the memory and improves the data read/write speed.
## Development Guidelines
Mount:
```
mount(NULL, "/dev/shm", "ramfs", 0, NULL)
```
Create a directory:
```
mkdir(pathname, mode)
```
Create a file:
```
open(pathname, O_NONBLOCK | O_CREAT | O_RDWR, mode)
```
Read a directory:
```
dir = opendir(pathname)
ptr = readdir(dir)
closedir(dir)
```
Delete a file:
```
unlink(pathname)
```
Delete a directory:
```
rmdir(pathname)
```
Unmount:
```
umount("/dev/shm")
```
> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**<br/>
> - A ramfs file system can be mounted only once. Once mounted to a directory, it cannot be mounted to other directories.
>
> - Ramfs is under debugging and disabled by default. Do not use it in formal products.
# File Systems
A file system \(often abbreviated to FS\) provides an input and output manner for an OS. It implements the interaction with internal and external storage devices.
The file system provides standard POSIX operation APIs for the upper-layer system through the C library. For details, see the API reference of the C library. The Virtual File System \(VFS\) layer in kernel mode shields the differences between file systems. The basic architecture is as follows:
**Figure 1** Overall file system architecture
![](figures/overall-file-system-architecture.png "overall-file-system-architecture")
- **[Virtual File System](kernel-small-bundles-fs-virtual.md)**
- **[Supported File Systems](kernel-small-bundles-fs-support.md)**
- **[File System Adaptation](kernel-small-bundles-fs-new.md)**
# Extended Components
- **[System Call](kernel-small-bundles-system.md)**
- **[Dynamic Loading and Linking](kernel-small-bundles-linking.md)**
- **[Virtual Dynamic Shared Object](kernel-small-bundles-share.md)**
- **[LiteIPC](kernel-small-bundles-ipc.md)**
- **[File Systems](kernel-small-bundles-fs.md)**
# Kernel-Mode Memory Debugging
- **[Memory Information Statistics](kernel-small-debug-memory-info.md)**
- **[Memory Leak Check](kernel-small-debug-memory-leak.md)**
- **[Memory Corruption Check](kernel-small-debug-memory-corrupt.md)**
# Other Kernel Debugging Methods
- **[Dying Gasp](kernel-small-debug-trace-other-lastwords.md)**
- **[Common Fault Locating Methods](kernel-small-debug-trace-other-faqs.md)**
# Process Debugging
- **[CPUP](kernel-small-debug-process-cpu.md)**
# System Commands
- **[cpup](kernel-small-debug-shell-cmd-cpup.md)**
- **[date](kernel-small-debug-shell-cmd-date.md)**
- **[dmesg](kernel-small-debug-shell-cmd-dmesg.md)**
- **[exec](kernel-small-debug-shell-cmd-exec.md)**
- **[free](kernel-small-debug-shell-cmd-free.md)**
- **[help](kernel-small-debug-shell-cmd-help.md)**
- **[hwi](kernel-small-debug-shell-cmd-hwi.md)**
- **[kill](kernel-small-debug-shell-cmd-kill.md)**
- **[log](kernel-small-debug-shell-cmd-log.md)**
- **[memcheck](kernel-small-debug-shell-cmd-memcheck.md)**
- **[oom](kernel-small-debug-shell-cmd-oom.md)**
- **[pmm](kernel-small-debug-shell-cmd-pmm.md)**
- **[reset](kernel-small-debug-shell-cmd-reset.md)**
- **[sem](kernel-small-debug-shell-cmd-sem.md)**
- **[stack](kernel-small-debug-shell-cmd-stack.md)**
- **[su](kernel-small-debug-shell-cmd-su.md)**
- **[swtmr](kernel-small-debug-shell-cmd-swtmr.md)**
- **[systeminfo](kernel-small-debug-shell-cmd-sysinfo.md)**
- **[task](kernel-small-debug-shell-cmd-task.md)**
- **[uname](kernel-small-debug-shell-cmd-uname.md)**
- **[vmm](kernel-small-debug-shell-cmd-vmm.md)**
- **[watch](kernel-small-debug-shell-cmd-watch.md)**
- **[reboot](kernel-small-debug-shell-cmd-reboot.md)**
- **[top](kernel-small-debug-shell-cmd-top.md)**
# Shell Command Reference
This chapter describes the functions, syntax, parameter ranges, usage, and examples of key system commands.
For details about the commands that are not described in this document, see the output of the [help](kernel-small-debug-shell-cmd-help.md) command. You can also use the **-h | --help** option of a command to view the help information about the command.
- **[System Commands](kernel-small-debug-shell-cmd.md)**
- **[File Commands](kernel-small-debug-shell-file.md)**
- **[Network Commands](kernel-small-debug-shell-net.md)**
# File Commands
- **[cat](kernel-small-debug-shell-file-cat.md)**
- **[cd](kernel-small-debug-shell-file-cd.md)**
- **[chgrp](kernel-small-debug-shell-file-chgrp.md)**
- **[chmod](kernel-small-debug-shell-file-chmod.md)**
- **[chown](kernel-small-debug-shell-file-chown.md)**
- **[cp](kernel-small-debug-shell-file-cp.md)**
- **[format](kernel-small-debug-shell-file-format.md)**
- **[ls](kernel-small-debug-shell-file-ls.md)**
- **[lsfd](kernel-small-debug-shell-file-lsfd.md)**
- **[mkdir](kernel-small-debug-shell-file-mkdir.md)**
- **[mount](kernel-small-debug-shell-file-mount.md)**
- **[partinfo](kernel-small-debug-shell-file-partinfo.md)**
- **[partition](kernel-small-debug-shell-file-partition.md)**
- **[pwd](kernel-small-debug-shell-file-pwd.md)**
- **[rm](kernel-small-debug-shell-file-rm.md)**
- **[rmdir](kernel-small-debug-shell-file-rmdir.md)**
- **[statfs](kernel-small-debug-shell-file-statfs.md)**
- **[sync](kernel-small-debug-shell-file-sync.md)**
- **[touch](kernel-small-debug-shell-file-touch.md)**
- **[writeproc](kernel-small-debug-shell-file-write.md)**
- **[umount](kernel-small-debug-shell-file-umount.md)**
- **[du](kernel-small-debug-shell-file-du.md)**
- **[mv](kernel-small-debug-shell-file-mv.md)**
# Network Commands
- **[arp](kernel-small-debug-shell-net-arp.md)**
- **[dhclient](kernel-small-debug-shell-net-dhclient.md)**
- **[ifconfig](kernel-small-debug-shell-net-ifconfig.md)**
- **[ipdebug](kernel-small-debug-shell-net-ipdebug.md)**
- **[netstat](kernel-small-debug-shell-net-netstat.md)**
- **[ntpdate](kernel-small-debug-shell-net-ntpdate.md)**
- **[ping](kernel-small-debug-shell-net-ping.md)**
- **[ping6](kernel-small-debug-shell-net-ping6.md)**
- **[telnet](kernel-small-debug-shell-net-telnet.md)**
- **[tftp](kernel-small-debug-shell-net-tftp.md)**
# Shell
- **[Introduction to the Shell](kernel-small-debug-shell-overview.md)**
- **[Shell Command Development Guidelines](kernel-small-debug-shell-guide.md)**
- **[Shell Command Programming Example](kernel-small-debug-shell-build.md)**
- **[Shell Command Reference](kernel-small-debug-shell-details.md)**
- **[Magic Key](kernel-small-debug-shell-magickey.md)**
- **[User-Mode Exception Information](kernel-small-debug-shell-error.md)**
# Basic Concepts
The musl libc library of the debug version provides maintenance and test methods, such as memory leak check, heap memory statistics, memory corruption check, and backtrace, to improve the efficiency of locating memory problems in user space.
Instrumentation is performed on the **malloc** and **free** APIs to log key node information. When memory is requested and released by a program, the memory node integrity is checked. When the program ends, memory statistics are provided for identifying memory leaks.
# Typical Memory Problems
## Use After Free \(UAF\)<a name="section4427132815445"></a>
- Requested memory block less than or equal to 0x1c000 bytes:
After the memory is released:
Read operation: If the magic number \(0xFEFEFEFE\) is read from the memory block released, UAF occurs.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>After **free** is called, the heap memory will not be released to the heap memory pool immediately. Instead, the heap memory is placed in a queue with a fixed length and filled with the magic number 0xFE. When the queue is full, the memory block first placed in the queue is released to the heap memory pool first.
Write operation: The memory debugging module cannot detect UAF errors from write operations.
- Requested memory block greater than 0x1c000 bytes:
The heap memory greater than 0x1c000 bytes must be requested by calling the **mmap** API via **malloc**. If the heap memory is accessed after being released, the user program will become abnormal \(because the memory region has been unmapped\).
## Double Free<a name="section827194818458"></a>
Double free errors occur when **free\(\)** is called more than once with the same memory address as an argument. When a double free error occurs, the user program exits unexpectedly.
## Heap Memory Node Corrupted<a name="section1763741216461"></a>
- Requested memory block less than or equal to 0x1c000 bytes:
When a heap memory node is corrupted, the user program exits unexpectedly, and the call stack that requests the heap memory of the node corrupted is output. The memory debugging module, however, cannot debug the memory corrupted by a wild pointer. For example, if the user program mem\_check has heap memory overwriting, you can use the command line to obtain the possible location of the memory corruption.
```
OHOS # ./mem_check --mwatch
OHOS #
==PID:6== Memory integrity information:
[TID:28 allocated addr: 0x272e1ea0, size: 0x120] The possible attacker was allocated from:
#00: <malloc+0x808>[0x640e8] -> /lib/libc.so
#01: <threadFunc1+0x7c>[0x21d0] -> mem_check
```
You can use the call stack parsing script to parse the call stack information.
- Requested memory block greater than 0x1c000 bytes:
When a large memory block \(greater than 0x1c000 bytes\) is requested by calling the **mmap** API via **malloc**, one more page of **PAGE\_SIZE** is allocated at the start and end of the memory region. The two pages are neither readable nor writeable. Any read or write operation to the pages may cause an exception of the user program.
# Working Principles
## Memory Leak Check<a name="section142061581018"></a>
The memory debugging module maintains 128 \(that is the maximum number of threads supported in the system\) linked lists for each process. The index of each linked list is the thread ID.
When memory is requested, key information is saved to the memory node control block, which is inserted to the corresponding linked list based on the thread ID.
When memory is released, the system matches the memory node control block based on the memory address to be released and deletes the control block.
**Figure 1** Heap memory node linked list<a name="fig4294145810543"></a>
![](figures/heap-memory-node-linked-list.png "heap-memory-node-linked-list")
When memory is allocated, the returned address is saved in a link register \(LR\). During the process running, the system adds information, such as the LR corresponding to the suspected leak, to the memory node control block. [Figure 2](#fig716011269106) shows the heap memory node information.
**Figure 2** Heap memory node information<a name="fig716011269106"></a>
![](figures/heap-memory-node-information.png "heap-memory-node-information")
**TID** indicates the thread ID; **PID** indicates the process ID; **ptr** indicates the address of the memory requested; **size** indicates the size of the requested memory; **lr\[_n_\]** indicates the address of the call stack, and _n_ is configurable.
When memory is released, the input parameter pointer in the **free** API is used to match the **ptr** field of the memory node. If the pointer is the same as the **ptr** field of the memory node, the memory node control block will be deleted.
You can export the memory debugging information of each process through the serial port or file, and use the addr2line tool to convert the exported information into the code lines that cause memory leaks. In this way, the memory leakage problem can be solved.
**Figure 3** Process of locating the code lines for a memory leak<a name="fig1562884220111"></a>
![](figures/process-of-locating-the-code-lines-for-a-memory-leak.png "process-of-locating-the-code-lines-for-a-memory-leak")
## Heap Memory Statistics<a name="section136902041337"></a>
You can collect statistics on the percentage of heap memory requested by each thread to provide data support for optimizing memory usage of user programs. The **malloc** and **free** APIs are involved in user-mode heap memory statistics. As shown in [Figure 1](#fig4294145810543), each process maintains 128 linked lists, and the index of each linked list is a thread ID. When heap memory is requested, the **ptr** and **size** information is recorded in the memory node control block, which is inserted to a linked list with the thread ID as the header. When the heap memory is released, the corresponding heap memory block is removed from the linked list based on the **ptr**. In addition, the system calculates the total heap memory used by the current thread and updates its heap memory usage and peak heap memory usage.
## Memory Integrity Check<a name="section196491231761"></a>
- If the memory requested by using **malloc** is less than or equal to 0x1c000 bytes, the heap allocation algorithm is used to allocate memory.
When a user program requests heap memory, information such as the check value is added to the heap memory node. If the check value is abnormal, it is probably that the previous heap memory block is overwritten. Currently, the scenario where the check value is damaged by a wild pointer cannot be identified. When memory is allocated or released, the memory node check value is verified. If the memory node is corrupted and the verification fails, the following information is output: TID, PID, and call stack information saved when the previous heap memory block of the corrupted node is allocated. You can use the addr2line tool to obtain the specific code line and rectify the fault.
**Figure 4** Adding a check value to the node header information<a name="fig2912164881817"></a>
![](figures/adding-a-check-value-to-the-node-header-information.png "adding-a-check-value-to-the-node-header-information")
When heap memory is released by using **free**, the memory block is not released immediately. Instead, the magic number 0xFE is written into the memory block, which is then placed in the free queue to prevent the memory block from being allocated by **malloc** within a certain period of time. When a wild pointer or **use-after-free** operation is performed to read the memory, an exception can be detected. However, this mechanism does not apply to write operations.
**Figure 5** Process of releasing memory<a name="fig3593750101916"></a>
![](figures/process-of-releasing-memory.png "process-of-releasing-memory")
- If the memory requested by using **malloc** is greater than 0x1c000 bytes, **mmap** is used to allocate memory.
When **mmap** is used to request a large memory block, one more page is allocated at the start and end of the memory region. The current **PAGE\_SIZE** of each page is **0x1000**. The permissions of the two pages are set to **PROT\_NONE** \(no read or write permission\) by using the **mprotect** API to prevent out-of-bounds read and write of memory. If out-of-bounds read and write of memory occurs, the user program becomes abnormal because the user does not have the read or write permission. The code logic can be identified based on the abnormal call stack information.
**Figure 6** Layout of the memory allocated by using the **mmap** mechanism of **malloc**<a name="fig4150122342016"></a>
![](figures/layout-of-the-memory-allocated-by-using-the-mmap-mechanism-of-malloc.png "layout-of-the-memory-allocated-by-using-the-mmap-mechanism-of-malloc")
# Available APIs
**Table 1** Memory debugging module APIs
<a name="table1415203765610"></a>
<table><thead align="left"><tr id="row134151837125611"><th class="cellrowborder" valign="top" width="12.821282128212822%" id="mcps1.2.4.1.1"><p id="p16415637105612"><a name="p16415637105612"></a><a name="p16415637105612"></a>Category</p>
</th>
<th class="cellrowborder" valign="top" width="29.832983298329836%" id="mcps1.2.4.1.2"><p id="p11415163718562"><a name="p11415163718562"></a><a name="p11415163718562"></a>API</p>
</th>
<th class="cellrowborder" valign="top" width="57.34573457345735%" id="mcps1.2.4.1.3"><p id="p1641533755612"><a name="p1641533755612"></a><a name="p1641533755612"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row12171174434013"><td class="cellrowborder" rowspan="4" valign="top" width="12.821282128212822%" headers="mcps1.2.4.1.1 "><p id="p989011256471"><a name="p989011256471"></a><a name="p989011256471"></a>Memory debugging</p>
</td>
<td class="cellrowborder" valign="top" width="29.832983298329836%" headers="mcps1.2.4.1.2 "><p id="p15630114884017"><a name="p15630114884017"></a><a name="p15630114884017"></a>mem_check_init</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p4171244164013"><a name="p4171244164013"></a><a name="p4171244164013"></a>Initializes the memory check module.</p>
</td>
</tr>
<tr id="row17223043124018"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1730695210400"><a name="p1730695210400"></a><a name="p1730695210400"></a>watch_mem</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p202242431404"><a name="p202242431404"></a><a name="p202242431404"></a>Obtains the thread-level heap memory usage.</p>
</td>
</tr>
<tr id="row536885134010"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p236819594010"><a name="p236819594010"></a><a name="p236819594010"></a>check_leak</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p736918564019"><a name="p736918564019"></a><a name="p736918564019"></a>Checks for heap memory leaks.</p>
</td>
</tr>
<tr id="row11567448194112"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p0568204814115"><a name="p0568204814115"></a><a name="p0568204814115"></a>check_heap_integrity</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p05681348204114"><a name="p05681348204114"></a><a name="p05681348204114"></a>Checks the heap memory integrity.</p>
</td>
</tr>
<tr id="row1141513373562"><td class="cellrowborder" rowspan="3" valign="top" width="12.821282128212822%" headers="mcps1.2.4.1.1 "><p id="p16235102710486"><a name="p16235102710486"></a><a name="p16235102710486"></a>Call stack backtracking</p>
</td>
<td class="cellrowborder" valign="top" width="29.832983298329836%" headers="mcps1.2.4.1.2 "><p id="p17765212416"><a name="p17765212416"></a><a name="p17765212416"></a>backtrace</p>
</td>
<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p1972971913115"><a name="p1972971913115"></a><a name="p1972971913115"></a>Obtains the address information of the call stack.</p>
</td>
</tr>
<tr id="row18483936115014"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p14833367501"><a name="p14833367501"></a><a name="p14833367501"></a>backtrace_symbols</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p174842362505"><a name="p174842362505"></a><a name="p174842362505"></a>Obtains symbol information based on address information.</p>
</td>
</tr>
<tr id="row101737479509"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p21741147125016"><a name="p21741147125016"></a><a name="p21741147125016"></a>print_trace</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p15174184755019"><a name="p15174184755019"></a><a name="p15174184755019"></a>Prints call stack information.</p>
</td>
</tr>
</tbody>
</table>
# Calling APIs
## Sample Code<a name="section5490173592518"></a>
The sample code explicitly calls the related APIs of the memory debugging module to check the memory.
```
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <debug.h> // Header file that includes the declaration of the memory debugging APIs
#define MALLOC_LEAK_SIZE 0x300
void func(void) {
char *ptr = malloc(MALLOC_LEAK_SIZE);
memset(ptr, '3', MALLOC_LEAK_SIZE);
}
int main()
{
mem_check_init(NULL); // Output the memory debugging information through the serial port. This function must be called before the user program requests the heap memory for the first time (generally called at the entry of the main function). Otherwise, the debugging information is inaccurate.
// mem_check_init("/storage/mem_debug.txt"); // Output the memory debugging information to the /storage/mem_debug.txt file. If the file fails to be created, output the information through the serial port.
char *ptr = malloc(MALLOC_LEAK_SIZE);
memset(ptr, '1', MALLOC_LEAK_SIZE);
watch_mem(); // Obtain the thread-level memory statistics in the current code.
func();
check_heap_integrity(); // Check the integrity of the heap memory nodes.
check_leak(); // Check whether a heap memory leak occurs in the current code. (Generally, the check result is accurate before the application exits. If the check is performed after the calling of malloc and before the calling of free, the result is inaccurate.)
return 0;
}
```
## Compilation
```
$ clang -o mem_check mem_check.c -funwind-tables -rdynamic -g -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos --sysroot=/home/<user-name>/directory/out/hispark_taurus/ipcamera_hispark_taurus/sysroot $(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a)
```
>![](../public_sys-resources/icon-note.gif) **NOTE** <br/>
>- In this example, the compiler path is written into an environment variable in the **.bashrc** file.
>- When compiling user programs and required libraries, add the option **-funwind-tables -rdynamic -g** for stack backtracking.
>- The **-mfloat-abi=softfp**, **-mcpu=cortex-a7**, and **-mfpu=neon-vfpv4** options specify the floating-point calculation optimization, chip architecture, and FPU, which must be the same as the compilation options used by the libc library. Otherwise, the libc library file cannot be found during the link time.
>- **-target arm-liteos** specifies the path of the library files related to the compiler.
>- **--sysroot=/home/<user-name\>/directory/out/hispark\_taurus/ipcamera\_hispark\_taurus/sysroot** specifies the root directory of the compiler library files. In this example, the OpenHarmony project code is stored in **/home/<user-name\>/directory**. The **out/hispark\_taurus/ipcamera\_hispark\_taurus** directory indicates the product specified by the **hb set** command during compilation. In this example, **ipcamera\_hispark\_taurus** is the product specified.
>- **$\(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a\)** specifies the path of the unwind library.
## Debugging Information
```
OHOS # ./mem_check
OHOS #
==PID:4== Heap memory statistics(bytes): // Heap memory statistics
[Check point]: // Call stack of the check point
#00: <main+0x38>[0x86c] -> mem_check
#01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so
[TID: 18, Used: 0x320] // The heap memory is occupied by thread No. 18. The current process has only one thread.
==PID:4== Total heap: 0x320 byte(s), Peak: 0x320 byte(s)
Check heap integrity ok! // Heap memory integrity check
==PID:4== Detected memory leak(s): // Memory leak information and call stack
[Check point]:
#00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so
#01: <main+0x44>[0x878] -> mem_check
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <main+0x1c>[0x850] -> mem_check
#01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <func+0x14>[0x810] -> mem_check
#01: <main+0x3c>[0x870] -> mem_check
#02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so
==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s).
==PID:4== Detected memory leak(s):
[Check point]:
#00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so
#01: <exit+0x28>[0x111ec] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <main+0x1c>[0x850] -> mem_check
#01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <func+0x14>[0x810] -> mem_check
#01: <main+0x3c>[0x870] -> mem_check
#02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so
==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s).
Check heap integrity ok!
```
## Call Stack Parsing
The **parse\_mem\_info.sh** script in **kernel/liteos\_a/tools/scripts/parse\_memory/** can be used to parse the call stack. You can use the script to convert the debug information into specific source code line number. In the following command, **mem\_debug.txt** stores the memory debugging information, and **elf1** and **elf2** are the executable and linkable format \(ELF\) files to parse.
```
$ ./parse_mem_info.sh mem_debug.txt elf1 elf2 elf3 ...
```
Example:
```
$ ./parse_mem_info.sh mem_debug.txt mem_check
Compiler is [gcc/llvm]: llvm
Now using addr2line ...
==PID:4== Heap memory statistics(bytes):
[Check point]:
#00: <main+0x38>[0x86c] at /usr1/xxx/TEST_ELF/mem_check.c:22
#01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so
[TID: 18, Used: 0x320]
==PID:4== Total heap: 0x320 byte(s), Peak: 0x320 byte(s)
Check heap integrity ok!
==PID:4== Detected memory leak(s):
[Check point]:
#00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so
#01: <main+0x44>[0x878] at /usr1/xxx/TEST_ELF/mem_check.c:28
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <main+0x1c>[0x850] at /usr1/xxx/TEST_ELF/mem_check.c:17
#01: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <func+0x14>[0x810] at /usr1/xxx/TEST_ELF/mem_check.c:9
#01: <main+0x3c>[0x870] at /usr1/xxx/TEST_ELF/mem_check.c:24
#02: <(null)+0x24baf9dc>[0x219dc] -> /lib/libc.so
==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s).
```
# Using the CLI
In addition to calling APIs to check the memory used by user-mode processes, you can run CLI commands to collect memory statistics, check for memory leaks, and check memory integrity.
```
--mwatch: initializes memory debugging, registers signals, and outputs memory debugging information through the serial port.
--mrecord <f_path>: initializes memory debugging, registers signals, and saves the memory debugging information to the f_path file. If the f_path file fails to be created, output the memory debugging information through the serial port.
```
If the process to debug does not exit, you can use the signal mechanism to obtain the corresponding information:
```
kill -35 <pid> # Check the thread-level heap memory usage.
kill -36 <pid> # Check for heap memory leaks.
kill -37 <pid> # Check whether the head node of the heap memory is complete.
```
## Sample Code<a name="section13793104782316"></a>
The sample code constructs a memory problem and uses the command line to perform memory debugging.
```
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define MALLOC_LEAK_SIZE 0x300
void func(void) {
char *ptr = malloc(MALLOC_LEAK_SIZE);
memset(ptr, '3', MALLOC_LEAK_SIZE);
}
int main()
{
char *ptr = malloc(MALLOC_LEAK_SIZE);
memset(ptr, '1', MALLOC_LEAK_SIZE);
func();
while (1);
}
```
## Compilation
For details, see [Calling APIs](kernel-small-debug-user-guide-use-api.md#compilation).
## Running the mwatch Command
```
OHOS # ./mem_check --mwatch // Run the task command to obtain the mem_check process PID, which is 4.
OHOS #
OHOS # kill -35 4 // Check heap memory statistics.
OHOS #
==PID:4== Heap memory statistics(bytes):
[Check point]:
#00: <arm_signal_process+0x5c>[0x58dfc] -> /lib/libc.so
[TID: 18, Used: 0x640]
==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s)
OHOS # kill -36 4 // Check for heap memory leaks.
OHOS #
==PID:4== Detected memory leak(s):
[Check point]:
#00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so
#01: <arm_signal_process+0x5c>[0x58dfc] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <main+0x14>[0x724] -> mem_check
#01: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <func+0x14>[0x6ec] -> mem_check
#01: <main+0x30>[0x740] -> mem_check
#02: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so
==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s).
OHOS # kill -37 4 // Check the integrity of the head node of the heap memory.
OHOS #
Check heap integrity ok!
```
## Call Stack Parsing<a name="section1880675510221"></a>
Save the debugging information to the **test.txt** file and use the script to parse the information to obtain the number of line where the memory leak occurs.
```
$ ./parse_mem_info.sh test.txt mem_check
Compiler is [gcc/llvm]: llvm
Now using addr2line ...
==PID:4== Detected memory leak(s):
[Check point]:
#00: <check_leak+0x1c4>[0x2da4c] -> /lib/libc.so
#01: <arm_signal_process+0x5c>[0x58dfc] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <main+0x14>[0x724] at /usr1/xxx/TEST_ELF/mem_check.c:14
#01: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <func+0x14>[0x6ec] at /usr1/xxx/TEST_ELF/mem_check.c:8
#01: <main+0x30>[0x740] at /usr1/xxx/TEST_ELF/mem_check.c:19
#02: <(null)+0x2555a9dc>[0x219dc] -> /lib/libc.so
==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s).
```
## Running the mrecord Command
1. Run the user program and specify the path of the file that stores the memory debugging information.
```
OHOS # ./mem_check --mrecord /storage/check.txt
```
2. Run the **kill -35 <_pid_\>** command to collect statistics on the memory information. The information is exported to a file. Run the **cat** command to view the information.
```
OHOS # kill -35 4
OHOS # Memory statistics information saved in /storage/pid(4)_check.txt
OHOS # cat /storage/pid(4)_check.txt
==PID:4== Heap memory statistics(bytes):
[Check point]:
#00: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so
[TID: 18, Used: 0x640]
==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s)
```
3. Run the **kill -36 <_pid_\>** command to check memory integrity. The information is exported to a file. Run the **cat** command to view the information.
```
OHOS # kill -36 4
OHOS # Leak check information saved in /storage/pid(4)_check.txt
OHOS # cat /storage/pid(4)_check.txt
==PID:4== Heap memory statistics(bytes):
[Check point]:
#00: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so
[TID: 18, Used: 0x640]
==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s)
==PID:4== Detected memory leak(s):
[Check point]:
#00: <check_leak+0x1c4>[0x2e38c] -> /lib/libc.so
#01: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <main+0x14>[0x724] -> mem_check
#01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <func+0x14>[0x6ec] -> mem_check
#01: <main+0x30>[0x740] -> mem_check
#02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so
==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s).
```
4. Run the **kill -9 <_pid_\>** command to kill the current process. After the process exits, a memory integrity check is performed by default. The check result is output to a file. You can run the **cat** command to view it.
```
OHOS # kill -9 4
OHOS # Leak check information saved in /storage/pid(4)_check.txt
Check heap integrity ok!
OHOS # cat /storage/pid(4)_check.txt
OHOS #
==PID:4== Heap memory statistics(bytes):
[Check point]:
#00: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so
[TID: 18, Used: 0x640]
==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s)
==PID:4== Detected memory leak(s):
[Check point]:
#00: <check_leak+0x1c4>[0x2e38c] -> /lib/libc.so
#01: <arm_signal_process+0x5c>[0x5973c] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <main+0x14>[0x724] -> mem_check
#01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <func+0x14>[0x6ec] -> mem_check
#01: <main+0x30>[0x740] -> mem_check
#02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so
==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s).
==PID:4== Detected memory leak(s):
[Check point]:
#00: <check_leak+0x1c4>[0x2e38c] -> /lib/libc.so
#01: <exit+0x28>[0x11b2c] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <main+0x14>[0x724] -> mem_check
#01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so
[TID:18 Leak:0x320 byte(s)] Allocated from:
#00: <func+0x14>[0x6ec] -> mem_check
#01: <main+0x30>[0x740] -> mem_check
#02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so
==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s).
```
>![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
>The preceding information recorded gradually is added to the file specified during initialization. Therefore, running the **cat** command can also display the historical information in the file.
此差异已折叠。
此差异已折叠。
此差异已折叠。
# Enhanced Kernel Features
- **[Memory Management](kernel-standard-mm.md)**
- **[Task Scheduling](kernel-standard-sched.md)**
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册