Skip to content

Commit 6f33817

Browse files
Yaxin WangJonathan Corbet
authored andcommitted
Docs/zh_CN: Translate physical_memory.rst to Simplified Chinese
This patch translates the "physical_memory.rst" document into Simplified Chinese to improve accessibility for Chinese-speaking developers and users. Signed-off-by: Yaxin Wang <[email protected]> Signed-off-by: Jiang Kun <[email protected]> Reviewed-by: Yanteng Si <[email protected]> Signed-off-by: xu xin <[email protected]> Signed-off-by: Jonathan Corbet <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 32643e1 commit 6f33817

File tree

2 files changed

+357
-0
lines changed

2 files changed

+357
-0
lines changed

Documentation/translations/zh_CN/mm/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Linux内存管理文档
5454
page_owner
5555
page_table_check
5656
page_tables
57+
physical_memory
5758
remap_file_pages
5859
split_page_table_lock
5960
vmalloced-kernel-stacks
Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
.. include:: ../disclaimer-zh_CN.rst
4+
5+
:Original: Documentation/mm/physical_memory.rst
6+
7+
:翻译:
8+
9+
王亚鑫 Yaxin Wang <[email protected]>
10+
11+
========
12+
物理内存
13+
========
14+
15+
Linux可用于多种架构,因此需要一个与架构无关的抽象来表示物理内存。本章描述
16+
了管理运行系统中物理内存的结构。
17+
18+
第一个与内存管理相关的主要概念是 `非一致性内存访问(NUMA)
19+
<https://en.wikipedia.org/wiki/Non-uniform_memory_access>`
20+
21+
在多核和多插槽机器中,内存可能被组织成不同的存储区,这些存储区根据与处理器
22+
的距离“不同”而有不同的访问开销。例如,可能为每个CPU分配内存存储区,或者为
23+
外围设备在附近分配一个非常适合DMA的内存存储区。
24+
25+
每个存储区被称为一个节点,节点在Linux中表示为 ``struct pglist_data``,
26+
即使是在UMA架构中也是这样表示。该结构总是通过 ``pg_data_t`` 来引用。特
27+
定节点的 ``pg_data_t`` 结构体可以通过NODE_DATA(nid)引用,其中nid被称
28+
为该节点的ID。
29+
30+
对于非一致性内存访问(NUMA)架构,节点数据结构在引导时由特定于架构的代码早
31+
期分配。通常,这些结构在其所在的内存区上本地分配。对于一致性内存访问(UMA)
32+
架构,只使用一个静态的 ``pg_data_t`` 结构体,称为 ``contig_page_data``。
33+
节点将会在 :ref:`节点 <nodes>` 章节中进一步讨论。
34+
35+
整个物理内存被划分为一个或多个被称为区域的块,这些区域表示内存的范围。这
36+
些范围通常由访问内存的架构限制来决定。在节点内,与特定区域对应的内存范围
37+
由 ``struct zone`` 结构体描述,该结构被定义为 ``zone_t``,每种区域都
38+
属于以下描述类型的一种。
39+
40+
* ``ZONE_DMA`` 和 ``ZONE_DMA32`` 在历史上代表适用于DMA的内存,这些
41+
内存由那些不能访问所有可寻址内存的外设访问。多年来,已经有了更好、更稳
42+
固的接口来获取满足特定DMA需求的内存(这些接口由
43+
Documentation/core-api/dma-api.rst 文档描述),但是 ``ZONE_DMA``
44+
和 ``ZONE_DMA32`` 仍然表示访问受限的内存范围。
45+
46+
取决于架构的不同,这两种区域可以在构建时通过关闭 ``CONFIG_ZONE_DMA`` 和
47+
``CONFIG_ZONE_DMA32`` 配置选项来禁用。一些64位的平台可能需要这两种区域,
48+
因为他们支持具有不同DMA寻址限制的外设。
49+
50+
* ``ZONE_NORMAL`` 是普通内存的区域,这种内存可以被内核随时访问。如果DMA
51+
设备支持将数据传输到所有可寻址的内存区域,那么可在该区域的页面上执行DMA
52+
操作。``ZONE_NORMAL`` 总是开启的。
53+
54+
* ``ZONE_HIGHMEM`` 是指那些没有在内核页表中永久映射的物理内存部分。该区
55+
域的内存只能通过临时映射被内核访问。该区域只在某些32位架构上可用,并且是
56+
通过 ``CONFIG_HIGHMEM`` 选项开启。
57+
58+
* ``ZONE_MOVABLE`` 是指可访问的普通内存区域,就像 ``ZONE_NORMAL``
59+
一样。不同之处在于 ``ZONE_MOVABLE`` 中的大多数页面内容是可移动的。
60+
这意味着这些页面的虚拟地址不会改变,但它们的内容可能会在不同的物理页面
61+
之间移动。通常,在内存热插拔期间填充 ``ZONE_MOVABLE``,在启动时也可
62+
以使用 ``kernelcore``、``movablecore`` 和 ``movable_node``
63+
这些内核命令行参数来填充。更多详细信息,请参阅内核文档
64+
Documentation/mm/page_migration.rst 和
65+
Documentation/admin-guide/mm/memory-hotplug.rst。
66+
67+
* ``ZONE_DEVICE`` 表示位于持久性内存(PMEM)和图形处理单元(GPU)
68+
等设备上的内存。它与RAM区域类型有不同的特性,并且它的存在是为了提供
69+
:ref:`struct page<Pages>` 结构和内存映射服务,以便设备驱动程序能
70+
识别物理地址范围。``ZONE_DEVICE`` 通过 ``CONFIG_ZONE_DEVICE``
71+
选项开启。
72+
73+
需要注意的是,许多内核操作只能使用 ``ZONE_NORMAL`` 来执行,因此它是
74+
性能最关键区域。区域在 :ref:`区域 <zones>` 章节中有更详细的讨论。
75+
76+
节点和区域范围之间的关系由固件报告的物理内存映射决定,另外也由内存寻址
77+
的架构约束以及内核命令行中的某些参数决定。
78+
79+
例如,在具有2GB RAM的x86统一内存架构(UMA)机器上运行32位内核时,整
80+
个内存将位于节点0,并且将有三个区域: ``ZONE_DMA``、 ``ZONE_NORMAL``
81+
和 ``ZONE_HIGHMEM``::
82+
83+
0 2G
84+
+-------------------------------------------------------------+
85+
| node 0 |
86+
+-------------------------------------------------------------+
87+
88+
0 16M 896M 2G
89+
+----------+-----------------------+--------------------------+
90+
| ZONE_DMA | ZONE_NORMAL | ZONE_HIGHMEM |
91+
+----------+-----------------------+--------------------------+
92+
93+
94+
在内核构建时关闭 ``ZONE_DMA`` 开启 ``ZONE_DMA32``,并且具有16GB
95+
RAM平均分配在两个节点上的arm64机器上,使用 ``movablecore=80%`` 参数
96+
启动时,``ZONE_DMA32``、``ZONE_NORMAL`` 和 ``ZONE_MOVABLE``
97+
位于节点0,而 ``ZONE_NORMAL`` 和 ``ZONE_MOVABLE`` 位于节点1::
98+
99+
100+
1G 9G 17G
101+
+--------------------------------+ +--------------------------+
102+
| node 0 | | node 1 |
103+
+--------------------------------+ +--------------------------+
104+
105+
1G 4G 4200M 9G 9320M 17G
106+
+---------+----------+-----------+ +------------+-------------+
107+
| DMA32 | NORMAL | MOVABLE | | NORMAL | MOVABLE |
108+
+---------+----------+-----------+ +------------+-------------+
109+
110+
111+
内存存储区可能位于交错的节点。在下面的例子中,一台x86机器有16GB的RAM分
112+
布在4个内存存储区上,偶数编号的内存存储区属于节点0,奇数编号的内存条属于
113+
节点1::
114+
115+
0 4G 8G 12G 16G
116+
+-------------+ +-------------+ +-------------+ +-------------+
117+
| node 0 | | node 1 | | node 0 | | node 1 |
118+
+-------------+ +-------------+ +-------------+ +-------------+
119+
120+
0 16M 4G
121+
+-----+-------+ +-------------+ +-------------+ +-------------+
122+
| DMA | DMA32 | | NORMAL | | NORMAL | | NORMAL |
123+
+-----+-------+ +-------------+ +-------------+ +-------------+
124+
125+
在这种情况下,节点0将覆盖从0到12GB的内存范围,而节点1将覆盖从4GB到16GB
126+
的内存范围。
127+
128+
.. _nodes_zh_CN:
129+
130+
节点
131+
====
132+
133+
正如我们所提到的,内存中的每个节点由 ``pg_data_t`` 描述,通过
134+
``struct pglist_data`` 结构体的类型定义。在分配页面时,默认情况下,Linux
135+
使用节点本地分配策略,从离当前运行CPU的最近节点分配内存。由于进程倾向于在同
136+
一个CPU上运行,很可能会使用当前节点的内存。分配策略可以由用户控制,如内核文
137+
档 Documentation/admin-guide/mm/numa_memory_policy.rst 中所述。
138+
139+
大多数NUMA(非统一内存访问)架构维护了一个指向节点结构的指针数组。这些实际
140+
的结构在启动过程中的早期被分配,这时特定于架构的代码解析了固件报告的物理内
141+
存映射。节点初始化的大部分工作是在由free_area_init()实现的启动过程之后
142+
完成,该函数在后面的小节 :ref:`初始化 <initialization>` 中有详细描述。
143+
144+
除了节点结构,内核还维护了一个名为 ``node_states`` 的 ``nodemask_t``
145+
位掩码数组。这个数组中的每个位掩码代表一组特定属性的节点,这些属性由
146+
``enum node_states`` 定义,定义如下:
147+
148+
``N_POSSIBLE``
149+
节点可能在某个时刻上线。
150+
151+
``N_ONLINE``
152+
节点已经上线。
153+
154+
``N_NORMAL_MEMORY``
155+
节点拥有普通内存。
156+
157+
``N_HIGH_MEMORY``
158+
节点拥有普通或高端内存。当关闭 ``CONFIG_HIGHMEM`` 配置时,
159+
也可以称为 ``N_NORMAL_MEMORY``。
160+
161+
``N_MEMORY``
162+
节点拥有(普通、高端、可移动)内存。
163+
164+
``N_CPU``
165+
节点拥有一个或多个CPU。
166+
167+
对于具有上述属性的每个节点,``node_states[<property>]``
168+
掩码中对应于节点ID的位会被置位。
169+
170+
例如,对于具有常规内存和CPU的节点2,第二个bit将被设置::
171+
172+
node_states[N_POSSIBLE]
173+
node_states[N_ONLINE]
174+
node_states[N_NORMAL_MEMORY]
175+
node_states[N_HIGH_MEMORY]
176+
node_states[N_MEMORY]
177+
node_states[N_CPU]
178+
179+
有关使用节点掩码(nodemasks)可能进行的各种操作,请参考
180+
``include/linux/nodemask.h``。
181+
182+
除此之外,节点掩码(nodemasks)提供用于遍历节点的宏,即
183+
``for_each_node()`` 和 ``for_each_online_node()``。
184+
185+
例如,要为每个在线节点调用函数 foo(),可以这样操作::
186+
187+
for_each_online_node(nid) {
188+
pg_data_t *pgdat = NODE_DATA(nid);
189+
190+
foo(pgdat);
191+
}
192+
193+
节点数据结构
194+
------------
195+
196+
节点结构 ``struct pglist_data`` 在 ``include/linux/mmzone.h``
197+
中声明。这里我们将简要描述这个结构体的字段:
198+
199+
通用字段
200+
~~~~~~~~
201+
202+
``node_zones``
203+
表示该节点的区域列表。并非所有区域都可能被填充,但这是
204+
完整的列表。它被该节点的node_zonelists以及其它节点的
205+
node_zonelists引用。
206+
207+
``node_zonelists``
208+
表示所有节点中所有区域的列表。此列表定义了分配内存时首选的区域
209+
顺序。``node_zonelists`` 在核心内存管理结构初始化期间,
210+
由 ``mm/page_alloc.c`` 中的 ``build_zonelists()``
211+
函数设置。
212+
213+
``nr_zones``
214+
表示此节点中已填充区域的数量。
215+
216+
``node_mem_map``
217+
对于使用FLATMEM内存模型的UMA系统,0号节点的 ``node_mem_map``
218+
表示每个物理帧的struct pages数组。
219+
220+
``node_page_ext``
221+
对于使用FLATMEM内存模型的UMA系统,0号节点的 ``node_page_ext``
222+
是struct pages的扩展数组。只有在构建时开启了 ``CONFIG_PAGE_EXTENSION``
223+
选项的内核中才可用。
224+
225+
``node_start_pfn``
226+
表示此节点中起始页面帧的页面帧号。
227+
228+
``node_present_pages``
229+
表示此节点中存在的物理页面的总数。
230+
231+
``node_spanned_pages``
232+
表示包括空洞在内的物理页面范围的总大小。
233+
234+
``node_size_lock``
235+
一个保护定义节点范围字段的锁。仅在开启了 ``CONFIG_MEMORY_HOTPLUG`` 或
236+
``CONFIG_DEFERRED_STRUCT_PAGE_INIT`` 配置选项中的某一个时才定义。提
237+
供了 ``pgdat_resize_lock()`` 和 ``pgdat_resize_unlock()`` 用来操作
238+
``node_size_lock``,而无需检查 ``CONFIG_MEMORY_HOTPLUG`` 或
239+
``CONFIG_DEFERRED_STRUCT_PAGE_INIT`` 选项。
240+
241+
``node_id``
242+
节点的节点ID(NID),从0开始。
243+
244+
``totalreserve_pages``
245+
这是每个节点保留的页面,这些页面不可用于用户空间分配。
246+
247+
``first_deferred_pfn``
248+
如果大型机器上的内存初始化被推迟,那么第一个PFN(页帧号)是需要初始化的。
249+
在开启了 ``CONFIG_DEFERRED_STRUCT_PAGE_INIT`` 选项时定义。
250+
251+
``deferred_split_queue``
252+
每个节点的大页队列,这些大页的拆分被推迟了。仅在开启了 ``CONFIG_TRANSPARENT_HUGEPAGE``
253+
配置选项时定义。
254+
255+
``__lruvec``
256+
每个节点的lruvec持有LRU(最近最少使用)列表和相关参数。仅在禁用了内存
257+
控制组(cgroups)时使用。它不应该直接访问,而应该使用 ``mem_cgroup_lruvec()``
258+
来查找lruvecs。
259+
260+
回收控制
261+
~~~~~~~~
262+
263+
另见内核文档 Documentation/mm/page_reclaim.rst 文件。
264+
265+
``kswapd``
266+
每个节点的kswapd内核线程实例。
267+
268+
``kswapd_wait``, ``pfmemalloc_wait``, ``reclaim_wait``
269+
同步内存回收任务的工作队列。
270+
271+
``nr_writeback_throttled``
272+
等待写回脏页时,被限制的任务数量。
273+
274+
``kswapd_order``
275+
控制kswapd尝试回收的order。
276+
277+
``kswapd_highest_zoneidx``
278+
kswapd线程可以回收的最高区域索引。
279+
280+
``kswapd_failures``
281+
kswapd无法回收任何页面的运行次数。
282+
283+
``min_unmapped_pages``
284+
无法回收的未映射文件支持的最小页面数量。由 ``vm.min_unmapped_ratio``
285+
系统控制台(sysctl)参数决定。在开启 ``CONFIG_NUMA`` 配置时定义。
286+
287+
``min_slab_pages``
288+
无法回收的SLAB页面的最少数量。由 ``vm.min_slab_ratio`` 系统控制台
289+
(sysctl)参数决定。在开启 ``CONFIG_NUMA`` 时定义。
290+
291+
``flags``
292+
控制回收行为的标志位。
293+
294+
内存压缩控制
295+
~~~~~~~~~~~~
296+
297+
``kcompactd_max_order``
298+
kcompactd应尝试实现的页面order。
299+
300+
``kcompactd_highest_zoneidx``
301+
kcompactd可以压缩的最高区域索引。
302+
303+
``kcompactd_wait``
304+
同步内存压缩任务的工作队列。
305+
306+
``kcompactd``
307+
每个节点的kcompactd内核线程实例。
308+
309+
``proactive_compact_trigger``
310+
决定是否使用主动压缩。由 ``vm.compaction_proactiveness`` 系统控
311+
制台(sysctl)参数控制。
312+
313+
统计信息
314+
~~~~~~~~
315+
316+
``per_cpu_nodestats``
317+
表示节点的Per-CPU虚拟内存统计信息。
318+
319+
``vm_stat``
320+
表示节点的虚拟内存统计数据。
321+
322+
.. _zones_zh_CN:
323+
324+
区域
325+
====
326+
327+
.. admonition:: Stub
328+
329+
本节内容不完整。请列出并描述相应的字段。
330+
331+
.. _pages_zh_CN:
332+
333+
334+
====
335+
336+
.. admonition:: Stub
337+
338+
本节内容不完整。请列出并描述相应的字段。
339+
340+
.. _folios_zh_CN:
341+
342+
页码
343+
====
344+
345+
.. admonition:: Stub
346+
347+
本节内容不完整。请列出并描述相应的字段。
348+
349+
.. _initialization_zh_CN:
350+
351+
初始化
352+
======
353+
354+
.. admonition:: Stub
355+
356+
本节内容不完整。请列出并描述相应的字段。

0 commit comments

Comments
 (0)