sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextEnglish}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget /mm/highmemmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/zh_TW/mm/highmemmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/it_IT/mm/highmemmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/ja_JP/mm/highmemmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/ko_KR/mm/highmemmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget/translations/sp_SP/mm/highmemmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageChinese (Simplified)uh1h hh _documenthsourceNlineNubhnote)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]h paragraph)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hh5Documentation/translations/zh_CN/disclaimer-zh_CN.rsthKhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubh field_list)}(hhh](hfield)}(hhh](h field_name)}(hOriginalh]hOriginal}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK/var/lib/git/docbuild/linux/Documentation/translations/zh_CN/mm/highmem.rsthKubh field_body)}(hDocumentation/mm/highmem.rst h]h)}(hDocumentation/mm/highmem.rsth]hDocumentation/mm/highmem.rst}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h翻译h]h翻译}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhKubh)}(h-司延腾 Yanteng Si h]h)}(h,司延腾 Yanteng Si h](h司延腾 Yanteng Si <}(hjhhhNhNubh reference)}(hsiyanteng@loongson.cnh]hsiyanteng@loongson.cn}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:siyanteng@loongson.cnuh1jhjubh>}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h校译h]h校译}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj>hhhKubh)}(hhh]h}(h]h ]h"]h$]h&]uh1hhj>ubeh}(h]h ]h"]h$]h&]uh1hhhhK hhhhubeh}(h]h ]h"]h$]h&]uh1hhhhhhhhKubhsection)}(hhh](htitle)}(h高内存处理h]h高内存处理}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1jihjfhhhhhK ubh)}(h/作者: Peter Zijlstra h](h作者: Peter Zijlstra <}(hjyhhhNhNubj)}(ha.p.zijlstra@chello.nlh]ha.p.zijlstra@chello.nl}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:a.p.zijlstra@chello.nluh1jhjyubh>}(hjyhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjfhhubhtopic)}(hhh]h bullet_list)}(hhh](h list_item)}(hhh]h)}(hhh]j)}(hhh]h高内存是什么?}(hjhhhNhNubah}(h]id6ah ]h"]h$]h&]refidid2uh1jhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hhh]j)}(hhh]h临时虚拟映射}(hjhhhNhNubah}(h]id7ah ]h"]h$]h&]refidid3uh1jhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hhh]j)}(hhh]h临时映射的成本}(hjhhhNhNubah}(h]id8ah ]h"]h$]h&]refidid4uh1jhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hhh]j)}(hhh]hi386 PAE}(hjhhhNhNubah}(h]id9ah ]h"]h$]h&]refidi386-paeuh1jhjubah}(h]h ]h"]h$]h&]uh1hhj ubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hhh]j)}(hhh]h函数}(hj5hhhNhNubah}(h]id10ah ]h"]h$]h&]refidid5uh1jhj2ubah}(h]h ]h"]h$]h&]uh1hhj/ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhhhNhNubah}(h]contentsah ](contentslocaleh"]contentsah$]h&]uh1jhhhKhjfhhubje)}(hhh](jj)}(h高内存是什么?h]h高内存是什么?}(hjdhhhNhNubah}(h]h ]h"]h$]h&]refidjuh1jihjahhhhhKubh)}(hX 当物理内存的大小接近或超过虚拟内存的最大大小时,就会使用高内存(highmem)。在这一点上,内 核不可能在任何时候都保持所有可用的物理内存的映射。这意味着内核需要开始使用它想访问的物理内 存的临时映射。h]hX 当物理内存的大小接近或超过虚拟内存的最大大小时,就会使用高内存(highmem)。在这一点上,内 核不可能在任何时候都保持所有可用的物理内存的映射。这意味着内核需要开始使用它想访问的物理内 存的临时映射。}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjahhubh)}(h没有被永久映射覆盖的那部分(物理)内存就是我们所说的 "高内存"。对于这个边界的确切位置,有 各种架构上的限制。h]h没有被永久映射覆盖的那部分(物理)内存就是我们所说的 “高内存”。对于这个边界的确切位置,有 各种架构上的限制。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjahhubh)}(hX例如,在i386架构中,我们选择将内核映射到每个进程的虚拟空间,这样我们就不必为内核的进入/退 出付出全部的TLB作废代价。这意味着可用的虚拟内存空间(i386上为4GiB)必须在用户和内核空间之 间进行划分。h]hX例如,在i386架构中,我们选择将内核映射到每个进程的虚拟空间,这样我们就不必为内核的进入/退 出付出全部的TLB作废代价。这意味着可用的虚拟内存空间(i386上为4GiB)必须在用户和内核空间之 间进行划分。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjahhubh)}(hv使用这种方法的架构的传统分配方式是3:1,3GiB用于用户空间,顶部的1GiB用于内核空间。::h]hu使用这种方法的架构的传统分配方式是3:1,3GiB用于用户空间,顶部的1GiB用于内核空间。:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK!hjahhubh literal_block)}(hm+--------+ 0xffffffff | Kernel | +--------+ 0xc0000000 | | | User | | | +--------+ 0x00000000h]hm+--------+ 0xffffffff | Kernel | +--------+ 0xc0000000 | | | User | | | +--------+ 0x00000000}hjsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1jhhhK#hjahhubh)}(h这意味着内核在任何时候最多可以映射1GiB的物理内存,但是由于我们需要虚拟地址空间来做其他事 情--包括访问其余物理内存的临时映射--实际的直接映射通常会更少(通常在~896MiB左右)。h]h这意味着内核在任何时候最多可以映射1GiB的物理内存,但是由于我们需要虚拟地址空间来做其他事 情--包括访问其余物理内存的临时映射--实际的直接映射通常会更少(通常在~896MiB左右)。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK+hjahhubh)}(h其他有mm上下文标签的TLB的架构可以有独立的内核和用户映射。然而,一些硬件(如一些ARM)在使 用mm上下文标签时,其虚拟空间有限。h]h其他有mm上下文标签的TLB的架构可以有独立的内核和用户映射。然而,一些硬件(如一些ARM)在使 用mm上下文标签时,其虚拟空间有限。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK.hjahhubeh}(h]jah ]h"]高内存是什么?ah$]h&]uh1jdhjfhhhhhKubje)}(hhh](jj)}(h临时虚拟映射h]h临时虚拟映射}(hjhhhNhNubah}(h]h ]h"]h$]h&]jrjuh1jihjhhhhhK3ubh)}(hl内核包含几种创建临时映射的方法。下面的列表按照使用的优先顺序显示了它们。h]hl内核包含几种创建临时映射的方法。下面的列表按照使用的优先顺序显示了它们。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK5hjhhubj)}(hhh](j)}(hXckmap_local_page()。这个函数是用来要求短期映射的。它可以从任何上下文(包括中断)中调用, 但是映射只能在获取它们的上下文中使用。 在可行的情况下,这个函数应该比其他所有的函数优先使用。 这些映射是线程本地和CPU本地的,这意味着映射只能从这个线程中访问,并且当映射处于活跃状 态时,线程被绑定到CPU上。尽管这个函数从来没有禁用过抢占,但在映射被处理之前,CPU不能 通过CPU-hotplug从系统中拔出。 在本地的kmap区域中采取pagefaults是有效的,除非获取本地映射的上下文由于其他原因不允许 这样做。 如前所述,缺页异常和抢占从未被禁用。没有必要禁用抢占,因为当上下文切换到一个不同的任务 时,离开的任务的映射被保存,而进入的任务的映射被恢复。 kmap_local_page()总是返回一个有效的虚拟地址,并且假定kunmap_local()不会失败。 在CONFIG_HIGHMEM=n的内核中,对于低内存页,它返回直接映射的虚拟地址。只有真正的高内 存页面才会被临时映射。因此,用户可以为那些已知不是来自ZONE_HIGHMEM的页面调用普通的 page_address()。然而,使用kmap_local_page() / kunmap_local()总是安全的。 虽然它比kmap()快得多,但在高内存的情况下,它对指针的有效性有限制。与kmap()映射相反, 本地映射只在调用者的上下文中有效,不能传递给其他上下文。这意味着用户必须绝对保证返回 地址的使用只限于映射它的线程。 大多数代码可以被设计成使用线程本地映射。因此,用户在设计他们的代码时,应该尽量避免使用 kmap(),将页面映射到将被使用的同一线程中,并优先使用kmap_local_page()。 嵌套kmap_local_page()和kmap_atomic()映射在一定程度上是允许的(最多到KMAP_TYPE_NR), 但是它们的调用必须严格排序,因为映射的实现是基于堆栈的。关于如何管理嵌套映射的细节, 请参见kmap_local_page() kdocs(包含在 "函数 "部分)。 h](h)}(hkmap_local_page()。这个函数是用来要求短期映射的。它可以从任何上下文(包括中断)中调用, 但是映射只能在获取它们的上下文中使用。h]hkmap_local_page()。这个函数是用来要求短期映射的。它可以从任何上下文(包括中断)中调用, 但是映射只能在获取它们的上下文中使用。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK7hjubh)}(hQ在可行的情况下,这个函数应该比其他所有的函数优先使用。h]hQ在可行的情况下,这个函数应该比其他所有的函数优先使用。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK:hjubh)}(hX!这些映射是线程本地和CPU本地的,这意味着映射只能从这个线程中访问,并且当映射处于活跃状 态时,线程被绑定到CPU上。尽管这个函数从来没有禁用过抢占,但在映射被处理之前,CPU不能 通过CPU-hotplug从系统中拔出。h]hX!这些映射是线程本地和CPU本地的,这意味着映射只能从这个线程中访问,并且当映射处于活跃状 态时,线程被绑定到CPU上。尽管这个函数从来没有禁用过抢占,但在映射被处理之前,CPU不能 通过CPU-hotplug从系统中拔出。}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKChjubh)}(hdkmap_local_page()总是返回一个有效的虚拟地址,并且假定kunmap_local()不会失败。h]hdkmap_local_page()总是返回一个有效的虚拟地址,并且假定kunmap_local()不会失败。}(hjLhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKFhjubh)}(hX>在CONFIG_HIGHMEM=n的内核中,对于低内存页,它返回直接映射的虚拟地址。只有真正的高内 存页面才会被临时映射。因此,用户可以为那些已知不是来自ZONE_HIGHMEM的页面调用普通的 page_address()。然而,使用kmap_local_page() / kunmap_local()总是安全的。h]hX>在CONFIG_HIGHMEM=n的内核中,对于低内存页,它返回直接映射的虚拟地址。只有真正的高内 存页面才会被临时映射。因此,用户可以为那些已知不是来自ZONE_HIGHMEM的页面调用普通的 page_address()。然而,使用kmap_local_page() / kunmap_local()总是安全的。}(hjZhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKHhjubh)}(hX%虽然它比kmap()快得多,但在高内存的情况下,它对指针的有效性有限制。与kmap()映射相反, 本地映射只在调用者的上下文中有效,不能传递给其他上下文。这意味着用户必须绝对保证返回 地址的使用只限于映射它的线程。h]hX%虽然它比kmap()快得多,但在高内存的情况下,它对指针的有效性有限制。与kmap()映射相反, 本地映射只在调用者的上下文中有效,不能传递给其他上下文。这意味着用户必须绝对保证返回 地址的使用只限于映射它的线程。}(hjhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKLhjubh)}(h大多数代码可以被设计成使用线程本地映射。因此,用户在设计他们的代码时,应该尽量避免使用 kmap(),将页面映射到将被使用的同一线程中,并优先使用kmap_local_page()。h]h大多数代码可以被设计成使用线程本地映射。因此,用户在设计他们的代码时,应该尽量避免使用 kmap(),将页面映射到将被使用的同一线程中,并优先使用kmap_local_page()。}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKPhjubh)}(hX+嵌套kmap_local_page()和kmap_atomic()映射在一定程度上是允许的(最多到KMAP_TYPE_NR), 但是它们的调用必须严格排序,因为映射的实现是基于堆栈的。关于如何管理嵌套映射的细节, 请参见kmap_local_page() kdocs(包含在 "函数 "部分)。h]hX/嵌套kmap_local_page()和kmap_atomic()映射在一定程度上是允许的(最多到KMAP_TYPE_NR), 但是它们的调用必须严格排序,因为映射的实现是基于堆栈的。关于如何管理嵌套映射的细节, 请参见kmap_local_page() kdocs(包含在 “函数 “部分)。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKShjubeh}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hXykmap_atomic(). 这允许对单个页面进行非常短的时间映射。由于映射被限制在发布它的CPU上, 它表现得很好,但发布的任务因此被要求留在该CPU上直到它完成,以免其他任务取代它的映射。 kmap_atomic()也可以被中断上下文使用,因为它不睡眠,调用者也可能在调用kunmap_atomic() 后才睡眠。 内核中对kmap_atomic()的每次调用都会创建一个不可抢占的段,并禁用缺页异常。这可能是 未预期延迟的来源之一。因此用户应该选择kmap_local_page()而不是kmap_atomic()。 假设k[un]map_atomic()不会失败。 h](h)}(hkmap_atomic(). 这允许对单个页面进行非常短的时间映射。由于映射被限制在发布它的CPU上, 它表现得很好,但发布的任务因此被要求留在该CPU上直到它完成,以免其他任务取代它的映射。h]hkmap_atomic(). 这允许对单个页面进行非常短的时间映射。由于映射被限制在发布它的CPU上, 它表现得很好,但发布的任务因此被要求留在该CPU上直到它完成,以免其他任务取代它的映射。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKWhjubh)}(hkmap_atomic()也可以被中断上下文使用,因为它不睡眠,调用者也可能在调用kunmap_atomic() 后才睡眠。h]hkmap_atomic()也可以被中断上下文使用,因为它不睡眠,调用者也可能在调用kunmap_atomic() 后才睡眠。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKZhjubh)}(h内核中对kmap_atomic()的每次调用都会创建一个不可抢占的段,并禁用缺页异常。这可能是 未预期延迟的来源之一。因此用户应该选择kmap_local_page()而不是kmap_atomic()。h]h内核中对kmap_atomic()的每次调用都会创建一个不可抢占的段,并禁用缺页异常。这可能是 未预期延迟的来源之一。因此用户应该选择kmap_local_page()而不是kmap_atomic()。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK]hjubh)}(h&假设k[un]map_atomic()不会失败。h]h&假设k[un]map_atomic()不会失败。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK`hjubeh}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hXkmap()。这应该被用来对单个页面进行短时间的映射,对抢占或迁移没有限制。它会带来开销, 因为映射空间是受限制的,并且受到全局锁的保护,以实现同步。当不再需要映射时,必须用 kunmap()释放该页被映射的地址。 映射变化必须广播到所有CPU(核)上,kmap()还需要在kmap的池被回绕(TLB项用光了,需要从第 一项复用)时进行全局TLB无效化,当映射空间被完全利用时,它可能会阻塞,直到有一个可用的 槽出现。因此,kmap()只能从可抢占的上下文中调用。 如果一个映射必须持续相对较长的时间,上述所有的工作都是必要的,但是内核中大部分的 高内存映射都是短暂的,而且只在一个地方使用。这意味着在这种情况下,kmap()的成本大 多被浪费了。kmap()并不是为长期映射而设计的,但是它已经朝着这个方向发展了,在较新 的代码中强烈不鼓励使用它,前面的函数集应该是首选。 在64位系统中,调用kmap_local_page()、kmap_atomic()和kmap()没有实际作用,因为64位 地址空间足以永久映射所有物理内存页面。 h](h)}(hX!kmap()。这应该被用来对单个页面进行短时间的映射,对抢占或迁移没有限制。它会带来开销, 因为映射空间是受限制的,并且受到全局锁的保护,以实现同步。当不再需要映射时,必须用 kunmap()释放该页被映射的地址。h]hX!kmap()。这应该被用来对单个页面进行短时间的映射,对抢占或迁移没有限制。它会带来开销, 因为映射空间是受限制的,并且受到全局锁的保护,以实现同步。当不再需要映射时,必须用 kunmap()释放该页被映射的地址。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKbhjubhdefinition_list)}(hhh]hdefinition_list_item)}(hX?映射变化必须广播到所有CPU(核)上,kmap()还需要在kmap的池被回绕(TLB项用光了,需要从第 一项复用)时进行全局TLB无效化,当映射空间被完全利用时,它可能会阻塞,直到有一个可用的 槽出现。因此,kmap()只能从可抢占的上下文中调用。 h](hterm)}(hy映射变化必须广播到所有CPU(核)上,kmap()还需要在kmap的池被回绕(TLB项用光了,需要从第h]hy映射变化必须广播到所有CPU(核)上,kmap()还需要在kmap的池被回绕(TLB项用光了,需要从第}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhhhKhhjubh definition)}(hhh]h)}(h一项复用)时进行全局TLB无效化,当映射空间被完全利用时,它可能会阻塞,直到有一个可用的 槽出现。因此,kmap()只能从可抢占的上下文中调用。h]h一项复用)时进行全局TLB无效化,当映射空间被完全利用时,它可能会阻塞,直到有一个可用的 槽出现。因此,kmap()只能从可抢占的上下文中调用。}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKghj ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhhhKhhjubah}(h]h ]h"]h$]h&]uh1jhjubh)}(hX如果一个映射必须持续相对较长的时间,上述所有的工作都是必要的,但是内核中大部分的 高内存映射都是短暂的,而且只在一个地方使用。这意味着在这种情况下,kmap()的成本大 多被浪费了。kmap()并不是为长期映射而设计的,但是它已经朝着这个方向发展了,在较新 的代码中强烈不鼓励使用它,前面的函数集应该是首选。h]hX如果一个映射必须持续相对较长的时间,上述所有的工作都是必要的,但是内核中大部分的 高内存映射都是短暂的,而且只在一个地方使用。这意味着在这种情况下,kmap()的成本大 多被浪费了。kmap()并不是为长期映射而设计的,但是它已经朝着这个方向发展了,在较新 的代码中强烈不鼓励使用它,前面的函数集应该是首选。}(hj,hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKjhjubh)}(h在64位系统中,调用kmap_local_page()、kmap_atomic()和kmap()没有实际作用,因为64位 地址空间足以永久映射所有物理内存页面。h]h在64位系统中,调用kmap_local_page()、kmap_atomic()和kmap()没有实际作用,因为64位 地址空间足以永久映射所有物理内存页面。}(hj:hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKohjubeh}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hvmap()。这可以用来将多个物理页长期映射到一个连续的虚拟空间。它需要全局同步来解除 映射。 h]h)}(hvmap()。这可以用来将多个物理页长期映射到一个连续的虚拟空间。它需要全局同步来解除 映射。h]hvmap()。这可以用来将多个物理页长期映射到一个连续的虚拟空间。它需要全局同步来解除 映射。}(hjRhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKrhjNubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]h ]h"]h$]h&]bullet*uh1jhhhK7hjhhubeh}(h]jah ]h"]临时虚拟映射ah$]h&]uh1jdhjfhhhhhK3ubje)}(hhh](jj)}(h临时映射的成本h]h临时映射的成本}(hjxhhhNhNubah}(h]h ]h"]h$]h&]jrjuh1jihjuhhhhhKvubh)}(hy创建临时映射的代价可能相当高。体系架构必须操作内核的页表、数据TLB和/或MMU的寄存器。h]hy创建临时映射的代价可能相当高。体系架构必须操作内核的页表、数据TLB和/或MMU的寄存器。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKxhjuhhubh)}(h如果CONFIG_HIGHMEM没有被设置,那么内核会尝试用一点计算来创建映射,将页面结构地址转换成 指向页面内容的指针,而不是去捣鼓映射。在这种情况下,解映射操作可能是一个空操作。h]h如果CONFIG_HIGHMEM没有被设置,那么内核会尝试用一点计算来创建映射,将页面结构地址转换成 指向页面内容的指针,而不是去捣鼓映射。在这种情况下,解映射操作可能是一个空操作。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKzhjuhhubh)}(h如果CONFIG_MMU没有被设置,那么就不可能有临时映射和高内存。在这种情况下,也将使用计算方法。h]h如果CONFIG_MMU没有被设置,那么就不可能有临时映射和高内存。在这种情况下,也将使用计算方法。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK}hjuhhubeh}(h]jah ]h"]临时映射的成本ah$]h&]uh1jdhjfhhhhhKvubje)}(hhh](jj)}(hi386 PAEh]hi386 PAE}(hjhhhNhNubah}(h]h ]h"]h$]h&]jrjuh1jihjhhhhhKubh)}(ht在某些情况下,i386 架构将允许你在 32 位机器上安装多达 64GiB 的内存。但这有一些后果:h]ht在某些情况下,i386 架构将允许你在 32 位机器上安装多达 64GiB 的内存。但这有一些后果:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj)}(hhh](j)}(h{Linux需要为系统中的每个页面建立一个页帧结构,而且页帧需要驻在永久映射中,这意味着: h]h)}(hzLinux需要为系统中的每个页面建立一个页帧结构,而且页帧需要驻在永久映射中,这意味着:h]hzLinux需要为系统中的每个页面建立一个页帧结构,而且页帧需要驻在永久映射中,这意味着:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(h你最多可以有896M/sizeof(struct page)页帧;由于页结构体是32字节的,所以最终会有 112G的页;然而,内核需要在内存中存储更多的页帧...... h]h)}(h你最多可以有896M/sizeof(struct page)页帧;由于页结构体是32字节的,所以最终会有 112G的页;然而,内核需要在内存中存储更多的页帧......h]h你最多可以有896M/sizeof(struct page)页帧;由于页结构体是32字节的,所以最终会有 112G的页;然而,内核需要在内存中存储更多的页帧......}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubj)}(hPAE使你的页表变大--这使系统变慢,因为更多的数据需要在TLB填充等方面被访问。一个好处 是,PAE有更多的PTE位,可以提供像NX和PAT这样的高级功能。 h]h)}(hPAE使你的页表变大--这使系统变慢,因为更多的数据需要在TLB填充等方面被访问。一个好处 是,PAE有更多的PTE位,可以提供像NX和PAT这样的高级功能。h]hPAE使你的页表变大--这使系统变慢,因为更多的数据需要在TLB填充等方面被访问。一个好处 是,PAE有更多的PTE位,可以提供像NX和PAT这样的高级功能。}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jhjhhhhhNubeh}(h]h ]h"]h$]h&]jljmuh1jhhhKhjhhubh)}(h一般的建议是,你不要在32位机器上使用超过8GiB的空间--尽管更多的空间可能对你和你的工作 量有用,但你几乎是靠你自己--不要指望内核开发者真的会很关心事情的进展情况。h]h一般的建议是,你不要在32位机器上使用超过8GiB的空间--尽管更多的空间可能对你和你的工作 量有用,但你几乎是靠你自己--不要指望内核开发者真的会很关心事情的进展情况。}(hj'hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h]j"ah ]h"]i386 paeah$]h&]uh1jdhjfhhhhhKubje)}(hhh](jj)}(h函数h]h函数}(hj?hhhNhNubah}(h]h ]h"]h$]h&]jrj>uh1jihj<hhhhhKubh)}(h该API在以下内核代码中:h]h该API在以下内核代码中:}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj<hhubh)}(hinclude/linux/highmem.hh]hinclude/linux/highmem.h}(hj[hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj<hhubh)}(h include/linux/highmem-internal.hh]h include/linux/highmem-internal.h}(hjihhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj<hhubeh}(h]jDah ]h"]函数ah$]h&]uh1jdhjfhhhhhKubeh}(h]id1ah ]h"]高内存处理ah$]h&]uh1jdhhhhhhhK ubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(jiN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh، _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jjj^jYjjjrjjjj9j"j{jDu nametypes}(jj^jjrjj9j{uh}(jjfjYjjjajjjjuj"jjDj<jjjjjjjjj>j5u footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}jK sRparse_messages]transform_messages] transformerN include_log]/Documentation/translations/zh_CN/mm/highmem.rst(NNNNta decorationNhhub.