.. SPDX-License-Identifier: GPL-2.0 .. include:: ../disclaimer-zh_CN.rst :Original: Documentation/scheduler/sched-domains.rst :翻译: å”艺舟 Tang Yizhou <tangyeechou@gmail.com> :æ ¡è¯‘: å¸å»¶è…¾ Yanteng Si <siyanteng@loongson.cn> ====== 调度域 ====== æ¯ä¸ªCPU有一个“基â€è°ƒåº¦åŸŸï¼ˆstruct sched_domain)。调度域层次结构从基调度域构建而æ¥ï¼Œå¯ 通过->parent指针自下而上é历。->parent必须以NULL结尾,调度域结构体必须是per-CPU的, å› ä¸ºå®ƒä»¬æ— é”æ›´æ–°ã€‚ æ¯ä¸ªè°ƒåº¦åŸŸç®¡è¾–数个CPU(å˜å‚¨åœ¨->spanå—æ®µä¸ï¼‰ã€‚一个调度域的span必须是它的å调度域spançš„ 超集(如有需求出现,这个é™åˆ¶å¯ä»¥æ”¾å®½ï¼‰ã€‚CPU i的基调度域必须至少管辖CPU i。æ¯ä¸ªCPUçš„ 顶层调度域通常将会管辖系统ä¸çš„全部CPUï¼Œå°½ç®¡ä¸¥æ ¼æ¥è¯´è¿™ä¸æ˜¯å¿…须的,å‡å¦‚æ˜¯è¿™æ ·ï¼Œä¼šå¯¼è‡´æŸäº› CPU出现永远ä¸ä¼šè¢«æŒ‡å®šä»»åŠ¡è¿è¡Œçš„æƒ…况,直到å…许的CPU掩ç 被显å¼è®¾å®šã€‚调度域的spanå—æ®µæ„味 ç€â€œåœ¨è¿™äº›CPUä¸åšè¿›ç¨‹è´Ÿè½½å‡è¡¡â€ã€‚ æ¯ä¸ªè°ƒåº¦åŸŸå¿…须具有一个或多个CPU调度组(struct sched_group),它们以å•å‘å¾ªçŽ¯é“¾è¡¨çš„å½¢å¼ ç»„ç»‡ï¼Œå˜å‚¨åœ¨->groups指针ä¸ã€‚这些组的CPU掩ç 的并集必须和调度域spanå—æ®µä¸€è‡´ã€‚->groups 指针指å‘的这些组包å«çš„CPU,必须被调度域管辖。组包å«çš„æ˜¯åªè¯»æ•°æ®ï¼Œè¢«åˆ›å»ºä¹‹åŽï¼Œå¯èƒ½è¢«å¤šä¸ª CPU共享。任æ„两个组的CPU掩ç 的交集ä¸ä¸€å®šä¸ºç©ºï¼Œå¦‚æžœæ˜¯è¿™ç§æƒ…况,对应调度域的SD_OVERLAP æ ‡å¿—ä½è¢«è®¾ç½®ï¼Œå®ƒç®¡è¾–的调度组å¯èƒ½ä¸èƒ½åœ¨å¤šä¸ªCPUä¸å…±äº«ã€‚ 调度域ä¸çš„è´Ÿè½½å‡è¡¡å‘生在调度组ä¸ã€‚也就是说,æ¯ä¸ªç»„被视为一个实体。组的负载被定义为它 管辖的æ¯ä¸ªCPU的负载之和。仅当组的负载ä¸å‡è¡¡åŽï¼Œä»»åŠ¡æ‰åœ¨ç»„之间å‘生è¿ç§»ã€‚ 在kernel/sched/core.cä¸ï¼Œsched_balance_trigger()在æ¯ä¸ªCPU上通过sched_tick() 周期执行。在当å‰è¿è¡Œé˜Ÿåˆ—下一个定期调度å†å¹³è¡¡äº‹ä»¶åˆ°è¾¾åŽï¼Œå®ƒå¼•å‘ä¸€ä¸ªè½¯ä¸æ–。负载å‡è¡¡çœŸæ£ 的工作由sched_balance_softirq()->sched_balance_domains()完æˆï¼Œåœ¨è½¯ä¸æ–ä¸Šä¸‹æ–‡ä¸æ‰§è¡Œ (SCHED_SOFTIRQ)。 åŽä¸€ä¸ªå‡½æ•°æœ‰ä¸¤ä¸ªå…¥å‚:当å‰CPUçš„è¿è¡Œé˜Ÿåˆ—ã€å®ƒåœ¨sched_tick()调用时是å¦ç©ºé—²ã€‚函数会从 当å‰CPU所在的基调度域开始è¿ä»£æ‰§è¡Œï¼Œå¹¶æ²¿ç€parent指针链å‘上进入更高层级的调度域。在è¿ä»£ 过程ä¸ï¼Œå‡½æ•°ä¼šæ£€æŸ¥å½“å‰è°ƒåº¦åŸŸæ˜¯å¦å·²ç»è€—尽了å†å¹³è¡¡çš„æ—¶é—´é—´éš”,如果是,它在该调度域è¿è¡Œ sched_balance_rq()。接下æ¥å®ƒæ£€æŸ¥çˆ¶è°ƒåº¦åŸŸï¼ˆå¦‚æžœå˜åœ¨ï¼‰ï¼Œå†åŽæ¥çˆ¶è°ƒåº¦åŸŸçš„父调度域,以æ¤ç±»æŽ¨ã€‚ èµ·åˆï¼Œsched_balance_rq()查找当å‰è°ƒåº¦åŸŸä¸æœ€ç¹å¿™çš„调度组。如果æˆåŠŸï¼Œåœ¨è¯¥è°ƒåº¦ç»„ç®¡è¾–çš„å…¨éƒ¨CPU çš„è¿è¡Œé˜Ÿåˆ—䏿‰¾å‡ºæœ€ç¹å¿™çš„è¿è¡Œé˜Ÿåˆ—。如能找到,对当å‰çš„CPUè¿è¡Œé˜Ÿåˆ—和新找到的最ç¹å¿™è¿è¡Œ 队列å‡åŠ é”,并把任务从最ç¹å¿™é˜Ÿåˆ—ä¸è¿ç§»åˆ°å½“å‰CPU上。被è¿ç§»çš„任务数é‡ç‰äºŽåœ¨å…ˆå‰è¿ä»£æ‰§è¡Œ ä¸è®¡ç®—出的该调度域的调度组的ä¸å‡è¡¡å€¼ã€‚ 实现调度域 ========== 基调度域会管辖CPU层次结构ä¸çš„第一层。对于超线程(SMT)而言,基调度域将会管辖åŒä¸€ä¸ªç‰©ç† CPU的全部虚拟CPU,æ¯ä¸ªè™šæ‹ŸCPU对应一个调度组。 在SMPä¸ï¼ŒåŸºè°ƒåº¦åŸŸçš„父调度域将会管辖åŒä¸€ä¸ªç»“点ä¸çš„全部物ç†CPU,æ¯ä¸ªè°ƒåº¦ç»„对应一个物ç†CPU。 接下æ¥ï¼Œå¦‚果是éžç»Ÿä¸€å†…å˜è®¿é—®ï¼ˆNUMA)系统,SMP调度域的父调度域将管辖整个机器,一个结点的 CPU掩ç å¯¹åº”ä¸€ä¸ªè°ƒåº¦ç»„ã€‚äº¦æˆ–ï¼Œä½ å¯ä»¥ä½¿ç”¨å¤šçº§NUMA;举例æ¥è¯´Opteron处ç†å™¨ï¼Œå¯èƒ½ä»…用一个 调度域æ¥è¦†ç›–它的一个NUMA层级。 实现者需è¦é˜…读include/linux/sched/sd_flags.h的注释:读SD_*æ¥äº†è§£å…·ä½“情况以åŠè°ƒåº¦åŸŸçš„ SDæ ‡å¿—ä½è°ƒèŠ‚äº†å“ªäº›ä¸œè¥¿ã€‚ 体系结构å¯ä»¥æŠŠæŒ‡å®šçš„æ‹“扑层级的通用调度域构建器和默认的SDæ ‡å¿—ä½è¦†ç›–掉,方法是创建一个 sched_domain_topology_level数组,并以该数组作为入å‚调用set_sched_topology()。 调度域调试基础设施å¯ä»¥é€šè¿‡CONFIG_SCHED_DEBUGå¼€å¯ï¼Œå¹¶åœ¨å¼€æœºå¯åŠ¨å‘½ä»¤è¡Œä¸å¢žåŠ â€œsched_verboseâ€ã€‚å¦‚æžœä½ å¿˜è®°è°ƒæ•´å¼€æœºå¯åŠ¨å‘½ä»¤è¡Œäº†ï¼Œä¹Ÿå¯ä»¥æ‰“å¼€ /sys/kernel/debug/sched/verbose开关。这将开å¯è°ƒåº¦åŸŸé”™è¯¯æ£€æŸ¥çš„è§£æžï¼Œå®ƒåº”该能æ•获(上文 æè¿°è¿‡çš„)ç»å¤§å¤šæ•°é”™è¯¯ï¼ŒåŒæ—¶ä»¥å¯è§†åŒ–æ ¼å¼æ‰“å°è°ƒåº¦åŸŸçš„结构。