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![](figures/physical-memory-usage-distribution.png "physical-memory-usage-distribution")
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    ![](figures/requesting-memory.png "requesting-memory")
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    ![](figures/releasing-memory.png "releasing-memory")
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>![](../public_sys-resources/icon-note.gif) **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