Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <wang.yaxin@zte.com.cn>
Signed-off-by: Jiang Kun <jiang.kun2@zte.com.cn>
Reviewed-by: Yanteng Si <si.yanteng@linux.dev>
Signed-off-by: xu xin <xu.xin16@zte.com.cn>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/20241028135321916ZWK032bHhlbncjvmzDkZs@zte.com.cn

authored by

Yaxin Wang and committed by
Jonathan Corbet
6f33817f 32643e10

+357
+1
Documentation/translations/zh_CN/mm/index.rst
··· 54 54 page_owner 55 55 page_table_check 56 56 page_tables 57 + physical_memory 57 58 remap_file_pages 58 59 split_page_table_lock 59 60 vmalloced-kernel-stacks
+356
Documentation/translations/zh_CN/mm/physical_memory.rst
··· 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 <wang.yaxin@zte.com.cn> 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 + 本节内容不完整。请列出并描述相应的字段。