1(_core_mm_api)=
2
3# 内存管理API
4
5## SLAB内存池
6
7SLAB内存池提供小内存对象的分配功能。
8
9### `void *kmalloc(unsigned long size, gfp_t gfp)`
10
11  获取小块的内存。
12
13#### 描述
14
15  kmalloc用于获取那些小于2M内存页大小的内存对象。可分配的内存对象大小为32bytes~1MBytes. 且分配的内存块大小、起始地址按照2的n次幂进行对齐。(比如,申请的是80bytes的内存空间,那么获得的内存对象大小为128bytes且内存地址按照128bytes对齐)
16
17##### 参数
18
19**size**
20
21  内存对象的大小
22
23**gfp**
24
25  标志位
26
27### `void *kzalloc(unsigned long size, gfp_t gfp)`
28
29#### 描述
30
31  获取小块的内存,并将其清零。其余功能与kmalloc相同。
32
33
34##### 参数
35
36**size**
37
38  内存对象的大小
39
40**gfp**
41
42  标志位
43
44### `unsigned long kfree(void *address)`
45
46  释放从slab分配的内存。
47
48#### 描述
49
50  该函数用于释放通过kmalloc申请的内存。如果`address`为NULL,则函数被调用后,无事发生。
51
52  请不要通过这个函数释放那些不是从`kmalloc()`或`kzalloc()`申请的内存,否则将会导致系统崩溃。
53
54##### 参数
55
56**address**
57
58  指向内存对象的起始地址的指针
59
60## 物理页管理
61
62DragonOS支持对物理页的直接操作
63
64### `struct Page *alloc_pages(unsigned int zone_select, int num, ul flags)`
65
66#### 描述
67
68  从物理页管理单元中申请一段连续的物理页
69
70#### 参数
71
72**zone_select**
73
74  要申请的物理页所位于的内存区域
75
76可选值:
77
78- `ZONE_DMA` DMA映射专用区域
79- `ZONE_NORMAL` 正常的物理内存区域,已在页表高地址处映射
80- `ZONE_UNMAPPED_IN_PGT` 尚未在页表中映射的区域
81
82**num**
83
84  要申请的连续物理页的数目,该值应当小于64
85
86**flags**
87
88  分配的页面要被设置成的属性
89
90可选值:
91
92- `PAGE_PGT_MAPPED` 页面在页表中已被映射
93- `PAGE_KERNEL_INIT` 内核初始化所占用的页
94- `PAGE_DEVICE` 设备MMIO映射的内存
95- `PAGE_KERNEL` 内核层页
96- `PAGE_SHARED` 共享页
97
98#### 返回值
99
100##### 成功
101
102  成功申请则返回指向起始页面的Page结构体的指针
103
104##### 失败
105
106  当ZONE错误或内存不足时,返回`NULL`
107
108### `void free_pages(struct Page *page, int number)`
109
110#### 描述
111
112  从物理页管理单元中释放一段连续的物理页。
113
114#### 参数
115
116**page**
117
118  要释放的第一个物理页的Page结构体
119
120**number**
121
122  要释放的连续内存页的数量。该值应小于64
123
124## 页表管理
125
126### `int mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool use4k)`
127
128#### 描述
129
130  将一段物理地址映射到当前页表的指定虚拟地址处
131
132#### 参数
133
134**virt_addr_start**
135
136  虚拟地址的起始地址
137
138**phys_addr_start**
139
140  物理地址的起始地址
141
142**length**
143
144  要映射的地址空间的长度
145
146**flags**
147
148  页表项的属性
149
150**use4k**
151
152  使用4级页表,将地址区域映射为若干4K页
153
154### `int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user, bool flush, bool use4k)`
155
156#### 描述
157
158  将一段物理地址映射到指定页表的指定虚拟地址处
159
160#### 参数
161
162**proc_page_table_addr**
163
164  指定的顶层页表的起始地址
165
166**is_phys**
167
168  该顶层页表地址是否为物理地址
169
170**virt_addr_start**
171
172  虚拟地址的起始地址
173
174**phys_addr_start**
175
176  物理地址的起始地址
177
178**length**
179
180  要映射的地址空间的长度
181
182**flags**
183
184  页表项的属性
185
186**user**
187
188  页面是否为用户态可访问
189
190**flush**
191
192  完成映射后,是否刷新TLB
193
194**use4k**
195
196  使用4级页表,将地址区域映射为若干4K页
197
198#### 返回值
199
200- 映射成功:0
201- 映射失败:-EFAULT
202
203### `void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul length)`
204
205#### 描述
206
207  取消给定页表中的指定地址空间的页表项映射。
208
209#### 参数
210
211**proc_page_table_addr**
212
213  指定的顶层页表的基地址
214
215**is_phys**
216
217  该顶层页表地址是否为物理地址
218
219**virt_addr_start**
220
221  虚拟地址的起始地址
222
223**length**
224
225  要取消映射的地址空间的长度
226
227### `mm_unmap_addr(virt_addr, length)`
228
229#### 描述
230
231  该宏定义用于取消当前进程的页表中的指定地址空间的页表项映射。
232
233#### 参数
234
235**virt_addr**
236
237  虚拟地址的起始地址
238
239**length**
240
241  要取消映射的地址空间的长度
242
243## 内存信息获取
244
245### `struct mm_stat_t mm_stat()`
246
247#### 描述
248
249  获取计算机目前的内存空间使用情况
250
251#### 参数
252
253254
255#### 返回值
256
257  返回值是一个`mm_mstat_t`结构体,该结构体定义于`mm/mm.h`中。其中包含了以下信息(单位均为字节):
258
259| 参数名        | 解释                      |
260| ---------- | ----------------------- |
261| total      | 计算机的总内存数量大小             |
262| used       | 已使用的内存大小                |
263| free       | 空闲物理页所占的内存大小            |
264| shared     | 共享的内存大小                 |
265| cache_used | 位于slab缓冲区中的已使用的内存大小     |
266| cache_free | 位于slab缓冲区中的空闲的内存大小      |
267| available  | 系统总空闲内存大小(包括kmalloc缓冲区) |