Lsphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextEnglish}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget/mm/split_page_table_lockmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/zh_TW/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/it_IT/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/ja_JP/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/ko_KR/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget,/translations/sp_SP/mm/split_page_table_lockmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageChinese (Simplified)uh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(h'分页表锁(split page table lock)h]h'分页表锁(split page table lock)}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhY/var/lib/git/docbuild/linux/Documentation/translations/zh_CN/mm/split_page_table_lock.rsthK ubh paragraph)}(h最初,mm->page_table_lock spinlock保护了mm_struct的所有页表。但是这种方 法导致了多线程应用程序的缺页异常可扩展性差,因为对锁的争夺很激烈。为了提高可扩 展性,我们引入了分页表锁。h]h最初,mm->page_table_lock spinlock保护了mm_struct的所有页表。但是这种方 法导致了多线程应用程序的缺页异常可扩展性差,因为对锁的争夺很激烈。为了提高可扩 展性,我们引入了分页表锁。}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(h有了分页表锁,我们就有了单独的每张表锁来顺序化对表的访问。目前,我们对PTE和 PMD表使用分页锁。对高层表的访问由mm->page_table_lock保护。h]h有了分页表锁,我们就有了单独的每张表锁来顺序化对表的访问。目前,我们对PTE和 PMD表使用分页锁。对高层表的访问由mm->page_table_lock保护。}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hG有一些辅助工具来锁定/解锁一个表和其他访问器函数:h]hG有一些辅助工具来锁定/解锁一个表和其他访问器函数:}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh block_quote)}(hX- pte_offset_map_lock() 映射pte并获取PTE表锁,返回所取锁的指针; - pte_unmap_unlock() 解锁和解映射PTE表; - pte_alloc_map_lock() 如果需要的话,分配PTE表并获取锁,如果分配失败,返回已获取的锁的指针 或NULL; - pte_lockptr() 返回指向PTE表锁的指针; - pmd_lock() 取得PMD表锁,返回所取锁的指针。 - pmd_lockptr() 返回指向PMD表锁的指针; h]h bullet_list)}(hhh](h list_item)}(hTpte_offset_map_lock() 映射pte并获取PTE表锁,返回所取锁的指针;h]hdefinition_list)}(hhh]hdefinition_list_item)}(hOpte_offset_map_lock() 映射pte并获取PTE表锁,返回所取锁的指针;h](hterm)}(hpte_offset_map_lock()h]hpte_offset_map_lock()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhubh definition)}(hhh]h)}(h9映射pte并获取PTE表锁,返回所取锁的指针;h]h9映射pte并获取PTE表锁,返回所取锁的指针;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubah}(h]h ]h"]h$]h&]uh1hhhubh)}(h3pte_unmap_unlock() 解锁和解映射PTE表;h]h)}(hhh]h)}(h.pte_unmap_unlock() 解锁和解映射PTE表;h](j)}(hpte_unmap_unlock()h]hpte_unmap_unlock()}(hjEhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjAubj)}(hhh]h)}(h解锁和解映射PTE表;h]h解锁和解映射PTE表;}(hjVhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjSubah}(h]h ]h"]h$]h&]uh1jhjAubeh}(h]h ]h"]h$]h&]uh1hhhhKhj>ubah}(h]h ]h"]h$]h&]uh1hhj:ubah}(h]h ]h"]h$]h&]uh1hhhubh)}(hpte_alloc_map_lock() 如果需要的话,分配PTE表并获取锁,如果分配失败,返回已获取的锁的指针 或NULL;h]h)}(hhh]h)}(hpte_alloc_map_lock() 如果需要的话,分配PTE表并获取锁,如果分配失败,返回已获取的锁的指针 或NULL;h](j)}(hpte_alloc_map_lock()h]hpte_alloc_map_lock()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hhh]h)}(hn如果需要的话,分配PTE表并获取锁,如果分配失败,返回已获取的锁的指针 或NULL;h]hn如果需要的话,分配PTE表并获取锁,如果分配失败,返回已获取的锁的指针 或NULL;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhj|ubah}(h]h ]h"]h$]h&]uh1hhhubh)}(h4pte_lockptr() 返回指向PTE表锁的指针;h]h)}(hhh]h)}(h/pte_lockptr() 返回指向PTE表锁的指针;h](j)}(h pte_lockptr()h]h pte_lockptr()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubj)}(hhh]h)}(h!返回指向PTE表锁的指针;h]h!返回指向PTE表锁的指针;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhhubh)}(h=pmd_lock() 取得PMD表锁,返回所取锁的指针。h]h)}(hhh]h)}(h8pmd_lock() 取得PMD表锁,返回所取锁的指针。h](j)}(h pmd_lock()h]h pmd_lock()}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hjubj)}(hhh]h)}(h-取得PMD表锁,返回所取锁的指针。h]h-取得PMD表锁,返回所取锁的指针。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK!hjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhK hjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhhubh)}(h5pmd_lockptr() 返回指向PMD表锁的指针; h]h)}(hhh]h)}(h0pmd_lockptr() 返回指向PMD表锁的指针; h](j)}(h pmd_lockptr()h]h pmd_lockptr()}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK#hjIubj)}(hhh]h)}(h!返回指向PMD表锁的指针;h]h!返回指向PMD表锁的指针;}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK#hj[ubah}(h]h ]h"]h$]h&]uh1jhjIubeh}(h]h ]h"]h$]h&]uh1hhhhK#hjFubah}(h]h ]h"]h$]h&]uh1hhjBubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]bullet-uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(h如果CONFIG_SPLIT_PTLOCK_CPUS(通常为4)小于或等于NR_CPUS,则在编译 时启用PTE表的分页表锁。如果分页锁被禁用,所有的表都由mm->page_table_lock 来保护。h]h如果CONFIG_SPLIT_PTLOCK_CPUS(通常为4)小于或等于NR_CPUS,则在编译 时启用PTE表的分页表锁。如果分页锁被禁用,所有的表都由mm->page_table_lock 来保护。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK%hhhhubh)}(hs如果PMD表启用了分页锁,并且架构支持它,那么PMD表的分页锁就会被启用(见 下文)。h]hs如果PMD表启用了分页锁,并且架构支持它,那么PMD表的分页锁就会被启用(见 下文)。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK)hhhhubh)}(hhh](h)}(hHugetlb 和分页表锁h]hHugetlb 和分页表锁}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK-ubh)}(hdHugetlb可以支持多种页面大小。我们只对PMD级别使用分页锁,但不对PUD使用。h]hdHugetlb可以支持多种页面大小。我们只对PMD级别使用分页锁,但不对PUD使用。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK/hjhhubh)}(hHugetlb特定的辅助函数:h]hHugetlb特定的辅助函数:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK1hjhhubh)}(h- huge_pte_lock() 对PMD_SIZE页面采取pmd分割锁,否则mm->page_table_lock; - huge_pte_lockptr() 返回指向表锁的指针。 h]h)}(hhh](h)}(hWhuge_pte_lock() 对PMD_SIZE页面采取pmd分割锁,否则mm->page_table_lock;h]h)}(hhh]h)}(hRhuge_pte_lock() 对PMD_SIZE页面采取pmd分割锁,否则mm->page_table_lock;h](j)}(hhuge_pte_lock()h]hhuge_pte_lock()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK3hjubj)}(hhh]h)}(hB对PMD_SIZE页面采取pmd分割锁,否则mm->page_table_lock;h]hB对PMD_SIZE页面采取pmd分割锁,否则mm->page_table_lock;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK4hjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhK3hjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1hhjubh)}(h7huge_pte_lockptr() 返回指向表锁的指针。 h]h)}(hhh]h)}(h2huge_pte_lockptr() 返回指向表锁的指针。 h](j)}(hhuge_pte_lockptr()h]hhuge_pte_lockptr()}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK6hj+ubj)}(hhh]h)}(h返回指向表锁的指针。h]h返回指向表锁的指针。}(hj@hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK6hj=ubah}(h]h ]h"]h$]h&]uh1jhj+ubeh}(h]h ]h"]h$]h&]uh1hhhhK6hj(ubah}(h]h ]h"]h$]h&]uh1hhj$ubah}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]jjuh1hhhhK3hjubah}(h]h ]h"]h$]h&]uh1hhhhK3hjhhubeh}(h]hugetlbah ]h"]hugetlb 和分页表锁ah$]h&]uh1hhhhhhhhK-ubh)}(hhh](h)}(h架构对分页表锁的支持h]h架构对分页表锁的支持}(hj}hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjzhhhhhK9ubh)}(h没有必要特别启用PTE分页表锁:所有需要的东西都由pagetable_pte_ctor() 和pagetable_pte_dtor()完成,它们必须在PTE表分配/释放时被调用。h]h没有必要特别启用PTE分页表锁:所有需要的东西都由pagetable_pte_ctor() 和pagetable_pte_dtor()完成,它们必须在PTE表分配/释放时被调用。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK;hjzhhubh)}(h确保架构不使用slab分配器来分配页表:slab使用page->slab_cache来分配其页 面。这个区域与page->ptl共享存储。h]h确保架构不使用slab分配器来分配页表:slab使用page->slab_cache来分配其页 面。这个区域与page->ptl共享存储。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK>hjzhhubh)}(hHPMD分页锁只有在你有两个以上的页表级别时才有意义。h]hHPMD分页锁只有在你有两个以上的页表级别时才有意义。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKAhjzhhubh)}(hq启用PMD分页锁需要在PMD表分配时调用pagetable_pmd_ctor(),在释放时调 用pagetable_pmd_dtor()。h]hq启用PMD分页锁需要在PMD表分配时调用pagetable_pmd_ctor(),在释放时调 用pagetable_pmd_dtor()。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKChjzhhubh)}(h分配通常发生在pmd_alloc_one()中,释放发生在pmd_free()和pmd_free_tlb() 中,但要确保覆盖所有的PMD表分配/释放路径:即X86_PAE在pgd_alloc()中预先 分配一些PMD。h]h分配通常发生在pmd_alloc_one()中,释放发生在pmd_free()和pmd_free_tlb() 中,但要确保覆盖所有的PMD表分配/释放路径:即X86_PAE在pgd_alloc()中预先 分配一些PMD。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKFhjzhhubh)}(hG一切就绪后,你可以设置CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK。h]hG一切就绪后,你可以设置CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKJhjzhhubh)}(hX注意:pagetable_pte_ctor()和pagetable_pmd_ctor()可能失败--必 须正确处理。h]hX注意:pagetable_pte_ctor()和pagetable_pmd_ctor()可能失败--必 须正确处理。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKLhjzhhubeh}(h]id1ah ]h"]架构对分页表锁的支持ah$]h&]uh1hhhhhhhhK9ubh)}(hhh](h)}(h page->ptlh]h page->ptl}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKPubh)}(hpage->ptl用于访问分割页表锁,其中'page'是包含该表的页面struct page。它 与page->private(以及union中的其他几个字段)共享存储。h]hpage->ptl用于访问分割页表锁,其中’page’是包含该表的页面struct page。它 与page->private(以及union中的其他几个字段)共享存储。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKRhjhhubh)}(hZ为了避免增加struct page的大小并获得最佳性能,我们使用了一个技巧:h]hZ为了避免增加struct page的大小并获得最佳性能,我们使用了一个技巧:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKUhjhhubh)}(hX- 如果spinlock_t适合于long,我们使用page->ptr作为spinlock,这样我们 就可以避免间接访问并节省一个缓存行。 - 如果spinlock_t的大小大于long的大小,我们使用page->ptl作为spinlock_t 的指针并动态分配它。这允许在启用DEBUG_SPINLOCK或DEBUG_LOCK_ALLOC的 情况下使用分页锁,但由于间接访问而多花了一个缓存行。 h]h)}(hhh](h)}(h如果spinlock_t适合于long,我们使用page->ptr作为spinlock,这样我们 就可以避免间接访问并节省一个缓存行。h]h)}(h如果spinlock_t适合于long,我们使用page->ptr作为spinlock,这样我们 就可以避免间接访问并节省一个缓存行。h]h如果spinlock_t适合于long,我们使用page->ptr作为spinlock,这样我们 就可以避免间接访问并节省一个缓存行。}(hj-hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKWhj)ubah}(h]h ]h"]h$]h&]uh1hhj&ubh)}(h如果spinlock_t的大小大于long的大小,我们使用page->ptl作为spinlock_t 的指针并动态分配它。这允许在启用DEBUG_SPINLOCK或DEBUG_LOCK_ALLOC的 情况下使用分页锁,但由于间接访问而多花了一个缓存行。 h]h)}(h如果spinlock_t的大小大于long的大小,我们使用page->ptl作为spinlock_t 的指针并动态分配它。这允许在启用DEBUG_SPINLOCK或DEBUG_LOCK_ALLOC的 情况下使用分页锁,但由于间接访问而多花了一个缓存行。h]h如果spinlock_t的大小大于long的大小,我们使用page->ptl作为spinlock_t 的指针并动态分配它。这允许在启用DEBUG_SPINLOCK或DEBUG_LOCK_ALLOC的 情况下使用分页锁,但由于间接访问而多花了一个缓存行。}(hjEhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKYhjAubah}(h]h ]h"]h$]h&]uh1hhj&ubeh}(h]h ]h"]h$]h&]jjuh1hhhhKWhj"ubah}(h]h ]h"]h$]h&]uh1hhhhKWhjhhubh)}(hmPTE表的spinlock_t分配在pagetable_pte_ctor()中,PMD表的spinlock_t 分配在pagetable_pmd_ctor()中。h]hmPTE表的spinlock_t分配在pagetable_pte_ctor()中,PMD表的spinlock_t 分配在pagetable_pmd_ctor()中。}(hjehhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK]hjhhubh)}(h@请不要直接访问page->ptl - -使用适当的辅助函数。h]h@请不要直接访问page->ptl - -使用适当的辅助函数。}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK`hjhhubeh}(h]page-ptlah ]h"] page->ptlah$]h&]uh1hhhhhhhhKPubeh}(h]split-page-table-lockah ]h"]'分页表锁(split page table lock)ah$]h&]uh1hhhhhhhhK ubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN 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}(jjjwjtjjjju nametypes}(jjwjjuh}(jhjtjjjzjju footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}jKsRparse_messages]transform_messages] transformerN include_log] decorationNhhub.