Csphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextEnglish}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget/scheduler/sched-domainsmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/zh_TW/scheduler/sched-domainsmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/it_IT/scheduler/sched-domainsmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/ja_JP/scheduler/sched-domainsmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/ko_KR/scheduler/sched-domainsmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/sp_SP/scheduler/sched-domainsmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageChinese (Simplified)uh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhhX/var/lib/git/docbuild/linux/Documentation/translations/zh_CN/scheduler/sched-domains.rsthKubhnote)}(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&]uh1hhhhhhKubh field_body)}(h*Documentation/scheduler/sched-domains.rst h]h)}(h)Documentation/scheduler/sched-domains.rsth]h)Documentation/scheduler/sched-domains.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翻译}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hhhKubh)}(h.唐艺舟 Tang Yizhou h]h)}(h-唐艺舟 Tang Yizhou h](h唐艺舟 Tang Yizhou <}(hj hhhNhNubh reference)}(htangyeechou@gmail.comh]htangyeechou@gmail.com}(hj*hhhNhNubah}(h]h ]h"]h$]h&]refurimailto:tangyeechou@gmail.comuh1j(hj ubh>}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhj ubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h校译h]h校译}(hjShhhNhNubah}(h]h ]h"]h$]h&]uh1hhjPhhhKubh)}(h-司延腾 Yanteng Si h]h)}(h,司延腾 Yanteng Si h](h司延腾 Yanteng Si <}(hjehhhNhNubj))}(hsiyanteng@loongson.cnh]hsiyanteng@loongson.cn}(hjmhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:siyanteng@loongson.cnuh1j(hjeubh>}(hjehhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK hjaubah}(h]h ]h"]h$]h&]uh1hhjPubeh}(h]h ]h"]h$]h&]uh1hhhhK hhhhubeh}(h]h ]h"]h$]h&]uh1hhhhhhhhKubhsection)}(hhh](htitle)}(h 调度域h]h 调度域}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjhhhhhKubh)}(hX每个CPU有一个“基”调度域(struct sched_domain)。调度域层次结构从基调度域构建而来,可 通过->parent指针自下而上遍历。->parent必须以NULL结尾,调度域结构体必须是per-CPU的, 因为它们无锁更新。h]hX每个CPU有一个“基”调度域(struct sched_domain)。调度域层次结构从基调度域构建而来,可 通过->parent指针自下而上遍历。->parent必须以NULL结尾,调度域结构体必须是per-CPU的, 因为它们无锁更新。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hX每个调度域管辖数个CPU(存储在->span字段中)。一个调度域的span必须是它的子调度域span的 超集(如有需求出现,这个限制可以放宽)。CPU i的基调度域必须至少管辖CPU i。每个CPU的 顶层调度域通常将会管辖系统中的全部CPU,尽管严格来说这不是必须的,假如是这样,会导致某些 CPU出现永远不会被指定任务运行的情况,直到允许的CPU掩码被显式设定。调度域的span字段意味 着“在这些CPU中做进程负载均衡”。h]hX每个调度域管辖数个CPU(存储在->span字段中)。一个调度域的span必须是它的子调度域span的 超集(如有需求出现,这个限制可以放宽)。CPU i的基调度域必须至少管辖CPU i。每个CPU的 顶层调度域通常将会管辖系统中的全部CPU,尽管严格来说这不是必须的,假如是这样,会导致某些 CPU出现永远不会被指定任务运行的情况,直到允许的CPU掩码被显式设定。调度域的span字段意味 着“在这些CPU中做进程负载均衡”。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hX/每个调度域必须具有一个或多个CPU调度组(struct sched_group),它们以单向循环链表的形式 组织,存储在->groups指针中。这些组的CPU掩码的并集必须和调度域span字段一致。->groups 指针指向的这些组包含的CPU,必须被调度域管辖。组包含的是只读数据,被创建之后,可能被多个 CPU共享。任意两个组的CPU掩码的交集不一定为空,如果是这种情况,对应调度域的SD_OVERLAP 标志位被设置,它管辖的调度组可能不能在多个CPU中共享。h]hX/每个调度域必须具有一个或多个CPU调度组(struct sched_group),它们以单向循环链表的形式 组织,存储在->groups指针中。这些组的CPU掩码的并集必须和调度域span字段一致。->groups 指针指向的这些组包含的CPU,必须被调度域管辖。组包含的是只读数据,被创建之后,可能被多个 CPU共享。任意两个组的CPU掩码的交集不一定为空,如果是这种情况,对应调度域的SD_OVERLAP 标志位被设置,它管辖的调度组可能不能在多个CPU中共享。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h调度域中的负载均衡发生在调度组中。也就是说,每个组被视为一个实体。组的负载被定义为它 管辖的每个CPU的负载之和。仅当组的负载不均衡后,任务才在组之间发生迁移。h]h调度域中的负载均衡发生在调度组中。也就是说,每个组被视为一个实体。组的负载被定义为它 管辖的每个CPU的负载之和。仅当组的负载不均衡后,任务才在组之间发生迁移。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK"hjhhubh)}(hXQ在kernel/sched/core.c中,sched_balance_trigger()在每个CPU上通过sched_tick() 周期执行。在当前运行队列下一个定期调度再平衡事件到达后,它引发一个软中断。负载均衡真正 的工作由sched_balance_softirq()->sched_balance_domains()完成,在软中断上下文中执行 (SCHED_SOFTIRQ)。h]hXQ在kernel/sched/core.c中,sched_balance_trigger()在每个CPU上通过sched_tick() 周期执行。在当前运行队列下一个定期调度再平衡事件到达后,它引发一个软中断。负载均衡真正 的工作由sched_balance_softirq()->sched_balance_domains()完成,在软中断上下文中执行 (SCHED_SOFTIRQ)。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK%hjhhubh)}(hX后一个函数有两个入参:当前CPU的运行队列、它在sched_tick()调用时是否空闲。函数会从 当前CPU所在的基调度域开始迭代执行,并沿着parent指针链向上进入更高层级的调度域。在迭代 过程中,函数会检查当前调度域是否已经耗尽了再平衡的时间间隔,如果是,它在该调度域运行 sched_balance_rq()。接下来它检查父调度域(如果存在),再后来父调度域的父调度域,以此类推。h]hX后一个函数有两个入参:当前CPU的运行队列、它在sched_tick()调用时是否空闲。函数会从 当前CPU所在的基调度域开始迭代执行,并沿着parent指针链向上进入更高层级的调度域。在迭代 过程中,函数会检查当前调度域是否已经耗尽了再平衡的时间间隔,如果是,它在该调度域运行 sched_balance_rq()。接下来它检查父调度域(如果存在),再后来父调度域的父调度域,以此类推。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK*hjhhubh)}(hX起初,sched_balance_rq()查找当前调度域中最繁忙的调度组。如果成功,在该调度组管辖的全部CPU 的运行队列中找出最繁忙的运行队列。如能找到,对当前的CPU运行队列和新找到的最繁忙运行 队列均加锁,并把任务从最繁忙队列中迁移到当前CPU上。被迁移的任务数量等于在先前迭代执行 中计算出的该调度域的调度组的不均衡值。h]hX起初,sched_balance_rq()查找当前调度域中最繁忙的调度组。如果成功,在该调度组管辖的全部CPU 的运行队列中找出最繁忙的运行队列。如能找到,对当前的CPU运行队列和新找到的最繁忙运行 队列均加锁,并把任务从最繁忙队列中迁移到当前CPU上。被迁移的任务数量等于在先前迭代执行 中计算出的该调度域的调度组的不均衡值。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK/hjhhubj)}(hhh](j)}(h实现调度域h]h实现调度域}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjhhhhhK5ubh)}(h基调度域会管辖CPU层次结构中的第一层。对于超线程(SMT)而言,基调度域将会管辖同一个物理 CPU的全部虚拟CPU,每个虚拟CPU对应一个调度组。h]h基调度域会管辖CPU层次结构中的第一层。对于超线程(SMT)而言,基调度域将会管辖同一个物理 CPU的全部虚拟CPU,每个虚拟CPU对应一个调度组。}(hj!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK7hjhhubh)}(hX在SMP中,基调度域的父调度域将会管辖同一个结点中的全部物理CPU,每个调度组对应一个物理CPU。 接下来,如果是非统一内存访问(NUMA)系统,SMP调度域的父调度域将管辖整个机器,一个结点的 CPU掩码对应一个调度组。亦或,你可以使用多级NUMA;举例来说Opteron处理器,可能仅用一个 调度域来覆盖它的一个NUMA层级。h]hX在SMP中,基调度域的父调度域将会管辖同一个结点中的全部物理CPU,每个调度组对应一个物理CPU。 接下来,如果是非统一内存访问(NUMA)系统,SMP调度域的父调度域将管辖整个机器,一个结点的 CPU掩码对应一个调度组。亦或,你可以使用多级NUMA;举例来说Opteron处理器,可能仅用一个 调度域来覆盖它的一个NUMA层级。}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK:hjhhubh)}(h实现者需要阅读include/linux/sched/sd_flags.h的注释:读SD_*来了解具体情况以及调度域的 SD标志位调节了哪些东西。h]h实现者需要阅读include/linux/sched/sd_flags.h的注释:读SD_*来了解具体情况以及调度域的 SD标志位调节了哪些东西。}(hj=hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK?hjhhubh)}(h体系结构可以把指定的拓扑层级的通用调度域构建器和默认的SD标志位覆盖掉,方法是创建一个 sched_domain_topology_level数组,并以该数组作为入参调用set_sched_topology()。h]h体系结构可以把指定的拓扑层级的通用调度域构建器和默认的SD标志位覆盖掉,方法是创建一个 sched_domain_topology_level数组,并以该数组作为入参调用set_sched_topology()。}(hjKhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKBhjhhubh)}(hX调度域调试基础设施可以通过CONFIG_SCHED_DEBUG开启,并在开机启动命令行中增加 “sched_verbose”。如果你忘记调整开机启动命令行了,也可以打开 /sys/kernel/debug/sched/verbose开关。这将开启调度域错误检查的解析,它应该能捕获(上文 描述过的)绝大多数错误,同时以可视化格式打印调度域的结构。h]hX调度域调试基础设施可以通过CONFIG_SCHED_DEBUG开启,并在开机启动命令行中增加 “sched_verbose”。如果你忘记调整开机启动命令行了,也可以打开 /sys/kernel/debug/sched/verbose开关。这将开启调度域错误检查的解析,它应该能捕获(上文 描述过的)绝大多数错误,同时以可视化格式打印调度域的结构。}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKEhjhhubeh}(h]id2ah ]h"]实现调度域ah$]h&]uh1jhjhhhhhK5ubeh}(h]id1ah ]h"] 调度域ah$]h&]uh1jhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(jN 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}(jtjqjljiu nametypes}(jtjluh}(jqjjiju 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]