1 # Physical Memory Management
2 
3 
4 ## Basic Concepts<a name="section210891719217"></a>
5 
6 Physical 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 
10 As 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 
15 The 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 
99 Use 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 
108 This 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.
116 VOID 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.
139 VOID 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 
176 ERROR:
177     (VOID)LOS_PhysPagesFree(&pageList);
178 }
179 
180 // Request multiple contiguous memory pages.
181 VOID 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 
202 UINT32 ExamplePhyMemCaseEntry(VOID)
203 {
204     OsPhysPagesAllocTest1();
205     OsPhysPagesAllocTest2();
206     OsPhysPagesAllocTest3();
207     return LOS_OK;
208 }
209 ```
210 
211 ### Verification<a name="section515091342819"></a>
212 
213 The development is successful if the return result is as follows:
214 
215 ```
216 LOS_PhysPagesAllocContiguous success
217 LOS_PhysPagesAlloc success
218 LOS_PhysPageAlloc success
219 ```
220 
221