1# Physical Memory Management 2 3 4## Basic Concepts<a name="section210891719217"></a> 5 6Physical 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. 7 8## Working Principles<a name="section111355315213"></a> 9 10As 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." 11 12**Figure 1** Physical memory usage distribution<a name="fig3648124205514"></a> 13![](figures/physical-memory-usage-distribution.png "physical-memory-usage-distribution") 14 15The 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. 16 17- Requesting memory 18 19 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. 20 21 **Figure 2** Requesting memory<a name="fig1319620135615"></a> 22 ![](figures/requesting-memory.png "requesting-memory") 23 24 25- Releasing memory 26 27 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. 28 29 **Figure 3** Releasing memory<a name="fig44001027165614"></a> 30 ![](figures/releasing-memory.png "releasing-memory") 31 32 33## Development Guidelines<a name="section393116496217"></a> 34 35### Available APIs<a name="section13210155619214"></a> 36 37**Table 1** Physical memory management module APIs 38 39<a name="table1415203765610"></a> 40<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> 41</th> 42<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> 43</th> 44<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> 45</th> 46</tr> 47</thead> 48<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> 49</td> 50<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> 51</td> 52<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> 53</td> 54</tr> 55<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> 56</td> 57<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> 58</td> 59</tr> 60<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> 61</td> 62<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> 63</td> 64</tr> 65<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> 66</td> 67<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> 68</td> 69<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> 70</td> 71</tr> 72<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> 73</td> 74<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> 75</td> 76</tr> 77<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> 78</td> 79<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> 80</td> 81</tr> 82<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> 83</td> 84<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> 85</td> 86<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> 87</td> 88</tr> 89<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> 90</td> 91<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> 92</td> 93</tr> 94</tbody> 95</table> 96 97### How to Develop<a name="section178441091231"></a> 98 99Use 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. 100 101>![](../public_sys-resources/icon-note.gif) **NOTE:** 102>- APIs used for requesting physical memory can be used only after memory initialization is complete by calling **OsSysMemInit**. 103>- The basic unit for memory allocation is page frame, that is, 4 KiB. 104>- 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. 105 106### Development Example<a name="section1258174015319"></a> 107 108This example calls APIs to request and release memory, including requesting one and multiple memory pages. 109 110``` 111#include "los_vm_phys.h" 112 113#define PHYS_PAGE_SIZE 0x4000 114 115// Request a page. 116VOID OsPhysPagesAllocTest3(VOID) 117{ 118 PADDR_T newPaddr; 119 VOID *kvaddr = NULL; 120 LosVmPage *newPage = NULL; 121 122 newPage = LOS_PhysPageAlloc(); 123 if (newPage == NULL) { 124 printf("LOS_PhysPageAlloc fail\n"); 125 return; 126 } 127 printf("LOS_PhysPageAlloc success\n"); 128 129 newPaddr = VM_PAGE_TO_PHYS(newPage); 130 kvaddr = OsVmPageToVaddr(newPage); 131 132 // Handle the physical memory 133 134 // Free the physical memory 135 LOS_PhysPageFree(newPage); 136} 137 138// Request multiple pages that do not need to be contiguous. 139VOID OsPhysPagesAllocTest2(VOID) 140{ 141 UINT32 sizeCount; 142 UINT32 count; 143 UINT32 size = PHYS_PAGE_SIZE; 144 LosVmPage *vmPageArray[PHYS_PAGE_SIZE >> PAGE_SHIFT] = { NULL }; 145 UINT32 i = 0; 146 LosVmPage *vmPage = NULL; 147 PADDR_T pa; 148 149 size = LOS_Align(size, PAGE_SIZE); 150 if (size == 0) { 151 return; 152 } 153 sizeCount = size >> PAGE_SHIFT; 154 155 LOS_DL_LIST_HEAD(pageList); 156 157 count = LOS_PhysPagesAlloc(sizeCount, &pageList); 158 if (count < sizeCount) { 159 printf("failed to allocate enough pages (ask %zu, got %zu)\n", sizeCount, count); 160 goto ERROR; 161 } 162 printf("LOS_PhysPagesAlloc success\n"); 163 while ((vmPage = LOS_ListRemoveHeadType(&pageList, LosVmPage, node))) { 164 pa = vmPage->physAddr; 165 vmPageArray[i++] = vmPage; 166 // Handle the physical memory 167 } 168 169 // Free the physical memory 170 for (i = 0; i < sizeCount; ++i) { 171 LOS_PhysPageFree(vmPageArray[i]); 172 } 173 174 return; 175 176ERROR: 177 (VOID)LOS_PhysPagesFree(&pageList); 178} 179 180// Request multiple contiguous memory pages. 181VOID OsPhysPagesAllocTest1(VOID) 182{ 183 VOID *ptr = NULL; 184 LosVmPage *page = NULL; 185 UINT32 size = PHYS_PAGE_SIZE; 186 187 ptr = LOS_PhysPagesAllocContiguous(ROUNDUP(size, PAGE_SIZE) >> PAGE_SHIFT); 188 if (ptr == NULL) { 189 printf("LOS_PhysPagesAllocContiguous fail\n"); 190 return; 191 } 192 193 printf("LOS_PhysPagesAllocContiguous success\n"); 194 195 // Handle the physical memory 196 197 // Free the physical memory 198 page = OsVmVaddrToPage((VOID *)ptr); 199 LOS_PhysPagesFreeContiguous((VOID *)ptr, size >> PAGE_SHIFT); 200} 201 202UINT32 ExamplePhyMemCaseEntry(VOID) 203{ 204 OsPhysPagesAllocTest1(); 205 OsPhysPagesAllocTest2(); 206 OsPhysPagesAllocTest3(); 207 return LOS_OK; 208} 209``` 210 211### Verification<a name="section515091342819"></a> 212 213The development is successful if the return result is as follows: 214 215``` 216LOS_PhysPagesAllocContiguous success 217LOS_PhysPagesAlloc success 218LOS_PhysPageAlloc success 219``` 220 221