1e41f4b71Sopenharmony_ci# Physical Memory Management 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci 4e41f4b71Sopenharmony_ci## Basic Concepts<a name="section210891719217"></a> 5e41f4b71Sopenharmony_ci 6e41f4b71Sopenharmony_ciPhysical memory is one of the most important resources on a computer. It is the memory space that is provided by the physical memory devices and can be directly addressed through the CPU bus. The physical memory provides temporary storage space for the OS and programs. The LiteOS-A kernel manages the physical memory via memory paging. Except the memory occupied by the kernel heap, other available memory is divided into page frames in the unit of 4 KiB. Memory is allocated and reclaimed by page frame. The kernel uses the buddy algorithm to manage free pages to reduce the fragmentation rate and improve the memory allocation and release efficiency. However, a small block may block the merge of a large block, causing a failure to allocate a large memory block. 7e41f4b71Sopenharmony_ci 8e41f4b71Sopenharmony_ci## Working Principles<a name="section111355315213"></a> 9e41f4b71Sopenharmony_ci 10e41f4b71Sopenharmony_ciAs shown in the following figure, the physical memory distribution of the LiteOS-A kernel consists of the kernel image, kernel heap, and physical pages. For details about the kernel heap, see "Heap Memory Management." 11e41f4b71Sopenharmony_ci 12e41f4b71Sopenharmony_ci**Figure 1** Physical memory usage distribution<a name="fig3648124205514"></a> 13e41f4b71Sopenharmony_ci 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ciThe buddy algorithm divides all free page frames into 9 memory block groups, each of which contains 2<sup>N</sup> page frames. For example, the memory block in group 0 has 2<sup>0</sup>, that is, 1 page frame. The memory block in the eighth group has 2<sup>8</sup>, that is, 256 page frames. Memory blocks of the same size are added to the same linked list for management. 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci- Requesting memory 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci When 12 KiB memory \(3 page frames\) is requested, the list in group 3 \(with 8 page frames\) meets the requirement. After 12 KiB memory is allocated, 20 KiB memory \(5 page frames\) is left. The 5 page frames can be divided into 4 \(2<sup>2</sup>\) page frames and 1 \(2<sup>0</sup>\) page frame. The 4 page frames have no buddy in the list, and therefore are inserted into list 2. The 1 page frame has a buddy in list 0. If the addresses of the two \(2<sup>0</sup>\) memory blocks are contiguous, the memory blocks are merged as 2 page frames \(2<sup>1</sup>\) and inserted to list 2. If the addresses are not contiguous, the two \(2<sup>0</sup>\) page frames are left in list 0. 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci **Figure 2** Requesting memory<a name="fig1319620135615"></a> 22e41f4b71Sopenharmony_ci  23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci- Releasing memory 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci When 12 KiB memory \(3 page frames\) is released, the 3 page frames can be divided into 2 \(2<sup>1</sup>\) page frames and 1 \(2<sup>0</sup>\) page frame. The 2 page frames can be merged with the memory in linked list 1 if their addresses are contiguous and inserted to list 2. The one page frame can be merged with the memory in linked list 0 if their addresses are contiguous and inserted to list 1. In this way, the memory is released based on the buddy mechanism. 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci **Figure 3** Releasing memory<a name="fig44001027165614"></a> 30e41f4b71Sopenharmony_ci  31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ci## Development Guidelines<a name="section393116496217"></a> 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci### Available APIs<a name="section13210155619214"></a> 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci**Table 1** Physical memory management module APIs 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci<a name="table1415203765610"></a> 40e41f4b71Sopenharmony_ci<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><strong id="b1878413376595"><a name="b1878413376595"></a><a name="b1878413376595"></a>Function</strong></p> 41e41f4b71Sopenharmony_ci</th> 42e41f4b71Sopenharmony_ci<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><strong id="b395935974010"><a name="b395935974010"></a><a name="b395935974010"></a>API</strong></p> 43e41f4b71Sopenharmony_ci</th> 44e41f4b71Sopenharmony_ci<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><strong id="b5959320418"><a name="b5959320418"></a><a name="b5959320418"></a>Description</strong></p> 45e41f4b71Sopenharmony_ci</th> 46e41f4b71Sopenharmony_ci</tr> 47e41f4b71Sopenharmony_ci</thead> 48e41f4b71Sopenharmony_ci<tbody><tr id="row11567448194112"><td class="cellrowborder" rowspan="3" valign="top" width="12.821282128212822%" headers="mcps1.2.4.1.1 "><p id="p1377313451287"><a name="p1377313451287"></a><a name="p1377313451287"></a>Requesting physical memory</p> 49e41f4b71Sopenharmony_ci</td> 50e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" width="29.832983298329836%" headers="mcps1.2.4.1.2 "><p id="p69501257634"><a name="p69501257634"></a><a name="p69501257634"></a>LOS_PhysPageAlloc</p> 51e41f4b71Sopenharmony_ci</td> 52e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p17950155714310"><a name="p17950155714310"></a><a name="p17950155714310"></a>Requests a physical page.</p> 53e41f4b71Sopenharmony_ci</td> 54e41f4b71Sopenharmony_ci</tr> 55e41f4b71Sopenharmony_ci<tr id="row1877155711548"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p687795718546"><a name="p687795718546"></a><a name="p687795718546"></a>LOS_PhysPagesAlloc</p> 56e41f4b71Sopenharmony_ci</td> 57e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p11877957115413"><a name="p11877957115413"></a><a name="p11877957115413"></a>Requests a physical page and adds it to the corresponding linked list.</p> 58e41f4b71Sopenharmony_ci</td> 59e41f4b71Sopenharmony_ci</tr> 60e41f4b71Sopenharmony_ci<tr id="row1141513373562"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1525917111411"><a name="p1525917111411"></a><a name="p1525917111411"></a>LOS_PhysPagesAllocContiguous</p> 61e41f4b71Sopenharmony_ci</td> 62e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p72594111245"><a name="p72594111245"></a><a name="p72594111245"></a>Requests memory of contiguous pages.</p> 63e41f4b71Sopenharmony_ci</td> 64e41f4b71Sopenharmony_ci</tr> 65e41f4b71Sopenharmony_ci<tr id="row11129518231"><td class="cellrowborder" rowspan="3" valign="top" width="12.821282128212822%" headers="mcps1.2.4.1.1 "><p id="p329691015710"><a name="p329691015710"></a><a name="p329691015710"></a>Releasing physical memory</p> 66e41f4b71Sopenharmony_ci</td> 67e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" width="29.832983298329836%" headers="mcps1.2.4.1.2 "><p id="p836211258313"><a name="p836211258313"></a><a name="p836211258313"></a>LOS_PhysPageFree</p> 68e41f4b71Sopenharmony_ci</td> 69e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p183626251933"><a name="p183626251933"></a><a name="p183626251933"></a>Releases a physical page.</p> 70e41f4b71Sopenharmony_ci</td> 71e41f4b71Sopenharmony_ci</tr> 72e41f4b71Sopenharmony_ci<tr id="row171671014107"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p368411237415"><a name="p368411237415"></a><a name="p368411237415"></a>LOS_PhysPagesFree</p> 73e41f4b71Sopenharmony_ci</td> 74e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p12684112320411"><a name="p12684112320411"></a><a name="p12684112320411"></a>Releases the physical pages added to a linked list.</p> 75e41f4b71Sopenharmony_ci</td> 76e41f4b71Sopenharmony_ci</tr> 77e41f4b71Sopenharmony_ci<tr id="row13796135518114"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p379616558114"><a name="p379616558114"></a><a name="p379616558114"></a>LOS_PhysPagesFreeContiguous</p> 78e41f4b71Sopenharmony_ci</td> 79e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1879675510114"><a name="p1879675510114"></a><a name="p1879675510114"></a>Releases memory of contiguous pages.</p> 80e41f4b71Sopenharmony_ci</td> 81e41f4b71Sopenharmony_ci</tr> 82e41f4b71Sopenharmony_ci<tr id="row757517464414"><td class="cellrowborder" rowspan="2" valign="top" width="12.821282128212822%" headers="mcps1.2.4.1.1 "><p id="p128501418185714"><a name="p128501418185714"></a><a name="p128501418185714"></a>Querying memory address</p> 83e41f4b71Sopenharmony_ci</td> 84e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" width="29.832983298329836%" headers="mcps1.2.4.1.2 "><p id="p147379529411"><a name="p147379529411"></a><a name="p147379529411"></a>LOS_VmPageGet</p> 85e41f4b71Sopenharmony_ci</td> 86e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" width="57.34573457345735%" headers="mcps1.2.4.1.3 "><p id="p1573711521144"><a name="p1573711521144"></a><a name="p1573711521144"></a>Obtains the physical page structure pointer based on the physical address.</p> 87e41f4b71Sopenharmony_ci</td> 88e41f4b71Sopenharmony_ci</tr> 89e41f4b71Sopenharmony_ci<tr id="row20508104412412"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1124573417"><a name="p1124573417"></a><a name="p1124573417"></a>LOS_PaddrToKVaddr</p> 90e41f4b71Sopenharmony_ci</td> 91e41f4b71Sopenharmony_ci<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p71217579414"><a name="p71217579414"></a><a name="p71217579414"></a>Obtains the kernel virtual address based on the physical address.</p> 92e41f4b71Sopenharmony_ci</td> 93e41f4b71Sopenharmony_ci</tr> 94e41f4b71Sopenharmony_ci</tbody> 95e41f4b71Sopenharmony_ci</table> 96e41f4b71Sopenharmony_ci 97e41f4b71Sopenharmony_ci### How to Develop<a name="section178441091231"></a> 98e41f4b71Sopenharmony_ci 99e41f4b71Sopenharmony_ciUse different APIs to request memory. Heap management APIs are recommended for requesting small amount of memory. Physical memory management APIs are recommended for requesting 4 KiB or larger memory. 100e41f4b71Sopenharmony_ci 101e41f4b71Sopenharmony_ci> **NOTE:** 102e41f4b71Sopenharmony_ci>- APIs used for requesting physical memory can be used only after memory initialization is complete by calling **OsSysMemInit**. 103e41f4b71Sopenharmony_ci>- The basic unit for memory allocation is page frame, that is, 4 KiB. 104e41f4b71Sopenharmony_ci>- To leave contiguous memory blocks for the modules that demand them, use **LOS\_PhysPagesAllocContiguous** to request contiguous memory blocks and use **LOS\_PhysPagesAlloc** to request memory blocks that are not contiguous. 105e41f4b71Sopenharmony_ci 106e41f4b71Sopenharmony_ci### Development Example<a name="section1258174015319"></a> 107e41f4b71Sopenharmony_ci 108e41f4b71Sopenharmony_ciThis example calls APIs to request and release memory, including requesting one and multiple memory pages. 109e41f4b71Sopenharmony_ci 110e41f4b71Sopenharmony_ci``` 111e41f4b71Sopenharmony_ci#include "los_vm_phys.h" 112e41f4b71Sopenharmony_ci 113e41f4b71Sopenharmony_ci#define PHYS_PAGE_SIZE 0x4000 114e41f4b71Sopenharmony_ci 115e41f4b71Sopenharmony_ci// Request a page. 116e41f4b71Sopenharmony_ciVOID OsPhysPagesAllocTest3(VOID) 117e41f4b71Sopenharmony_ci{ 118e41f4b71Sopenharmony_ci PADDR_T newPaddr; 119e41f4b71Sopenharmony_ci VOID *kvaddr = NULL; 120e41f4b71Sopenharmony_ci LosVmPage *newPage = NULL; 121e41f4b71Sopenharmony_ci 122e41f4b71Sopenharmony_ci newPage = LOS_PhysPageAlloc(); 123e41f4b71Sopenharmony_ci if (newPage == NULL) { 124e41f4b71Sopenharmony_ci printf("LOS_PhysPageAlloc fail\n"); 125e41f4b71Sopenharmony_ci return; 126e41f4b71Sopenharmony_ci } 127e41f4b71Sopenharmony_ci printf("LOS_PhysPageAlloc success\n"); 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci newPaddr = VM_PAGE_TO_PHYS(newPage); 130e41f4b71Sopenharmony_ci kvaddr = OsVmPageToVaddr(newPage); 131e41f4b71Sopenharmony_ci 132e41f4b71Sopenharmony_ci // Handle the physical memory 133e41f4b71Sopenharmony_ci 134e41f4b71Sopenharmony_ci // Free the physical memory 135e41f4b71Sopenharmony_ci LOS_PhysPageFree(newPage); 136e41f4b71Sopenharmony_ci} 137e41f4b71Sopenharmony_ci 138e41f4b71Sopenharmony_ci// Request multiple pages that do not need to be contiguous. 139e41f4b71Sopenharmony_ciVOID OsPhysPagesAllocTest2(VOID) 140e41f4b71Sopenharmony_ci{ 141e41f4b71Sopenharmony_ci UINT32 sizeCount; 142e41f4b71Sopenharmony_ci UINT32 count; 143e41f4b71Sopenharmony_ci UINT32 size = PHYS_PAGE_SIZE; 144e41f4b71Sopenharmony_ci LosVmPage *vmPageArray[PHYS_PAGE_SIZE >> PAGE_SHIFT] = { NULL }; 145e41f4b71Sopenharmony_ci UINT32 i = 0; 146e41f4b71Sopenharmony_ci LosVmPage *vmPage = NULL; 147e41f4b71Sopenharmony_ci PADDR_T pa; 148e41f4b71Sopenharmony_ci 149e41f4b71Sopenharmony_ci size = LOS_Align(size, PAGE_SIZE); 150e41f4b71Sopenharmony_ci if (size == 0) { 151e41f4b71Sopenharmony_ci return; 152e41f4b71Sopenharmony_ci } 153e41f4b71Sopenharmony_ci sizeCount = size >> PAGE_SHIFT; 154e41f4b71Sopenharmony_ci 155e41f4b71Sopenharmony_ci LOS_DL_LIST_HEAD(pageList); 156e41f4b71Sopenharmony_ci 157e41f4b71Sopenharmony_ci count = LOS_PhysPagesAlloc(sizeCount, &pageList); 158e41f4b71Sopenharmony_ci if (count < sizeCount) { 159e41f4b71Sopenharmony_ci printf("failed to allocate enough pages (ask %zu, got %zu)\n", sizeCount, count); 160e41f4b71Sopenharmony_ci goto ERROR; 161e41f4b71Sopenharmony_ci } 162e41f4b71Sopenharmony_ci printf("LOS_PhysPagesAlloc success\n"); 163e41f4b71Sopenharmony_ci while ((vmPage = LOS_ListRemoveHeadType(&pageList, LosVmPage, node))) { 164e41f4b71Sopenharmony_ci pa = vmPage->physAddr; 165e41f4b71Sopenharmony_ci vmPageArray[i++] = vmPage; 166e41f4b71Sopenharmony_ci // Handle the physical memory 167e41f4b71Sopenharmony_ci } 168e41f4b71Sopenharmony_ci 169e41f4b71Sopenharmony_ci // Free the physical memory 170e41f4b71Sopenharmony_ci for (i = 0; i < sizeCount; ++i) { 171e41f4b71Sopenharmony_ci LOS_PhysPageFree(vmPageArray[i]); 172e41f4b71Sopenharmony_ci } 173e41f4b71Sopenharmony_ci 174e41f4b71Sopenharmony_ci return; 175e41f4b71Sopenharmony_ci 176e41f4b71Sopenharmony_ciERROR: 177e41f4b71Sopenharmony_ci (VOID)LOS_PhysPagesFree(&pageList); 178e41f4b71Sopenharmony_ci} 179e41f4b71Sopenharmony_ci 180e41f4b71Sopenharmony_ci// Request multiple contiguous memory pages. 181e41f4b71Sopenharmony_ciVOID OsPhysPagesAllocTest1(VOID) 182e41f4b71Sopenharmony_ci{ 183e41f4b71Sopenharmony_ci VOID *ptr = NULL; 184e41f4b71Sopenharmony_ci LosVmPage *page = NULL; 185e41f4b71Sopenharmony_ci UINT32 size = PHYS_PAGE_SIZE; 186e41f4b71Sopenharmony_ci 187e41f4b71Sopenharmony_ci ptr = LOS_PhysPagesAllocContiguous(ROUNDUP(size, PAGE_SIZE) >> PAGE_SHIFT); 188e41f4b71Sopenharmony_ci if (ptr == NULL) { 189e41f4b71Sopenharmony_ci printf("LOS_PhysPagesAllocContiguous fail\n"); 190e41f4b71Sopenharmony_ci return; 191e41f4b71Sopenharmony_ci } 192e41f4b71Sopenharmony_ci 193e41f4b71Sopenharmony_ci printf("LOS_PhysPagesAllocContiguous success\n"); 194e41f4b71Sopenharmony_ci 195e41f4b71Sopenharmony_ci // Handle the physical memory 196e41f4b71Sopenharmony_ci 197e41f4b71Sopenharmony_ci // Free the physical memory 198e41f4b71Sopenharmony_ci page = OsVmVaddrToPage((VOID *)ptr); 199e41f4b71Sopenharmony_ci LOS_PhysPagesFreeContiguous((VOID *)ptr, size >> PAGE_SHIFT); 200e41f4b71Sopenharmony_ci} 201e41f4b71Sopenharmony_ci 202e41f4b71Sopenharmony_ciUINT32 ExamplePhyMemCaseEntry(VOID) 203e41f4b71Sopenharmony_ci{ 204e41f4b71Sopenharmony_ci OsPhysPagesAllocTest1(); 205e41f4b71Sopenharmony_ci OsPhysPagesAllocTest2(); 206e41f4b71Sopenharmony_ci OsPhysPagesAllocTest3(); 207e41f4b71Sopenharmony_ci return LOS_OK; 208e41f4b71Sopenharmony_ci} 209e41f4b71Sopenharmony_ci``` 210e41f4b71Sopenharmony_ci 211e41f4b71Sopenharmony_ci### Verification<a name="section515091342819"></a> 212e41f4b71Sopenharmony_ci 213e41f4b71Sopenharmony_ciThe development is successful if the return result is as follows: 214e41f4b71Sopenharmony_ci 215e41f4b71Sopenharmony_ci``` 216e41f4b71Sopenharmony_ciLOS_PhysPagesAllocContiguous success 217e41f4b71Sopenharmony_ciLOS_PhysPagesAlloc success 218e41f4b71Sopenharmony_ciLOS_PhysPageAlloc success 219e41f4b71Sopenharmony_ci``` 220e41f4b71Sopenharmony_ci 221