cfs调度类深入解刨——最新内核细节分析2

上一篇《cfs调度类深入解刨------最新内核细节分析1》中将kernel 7.0及以上版本中(较于kernel 6.6)的基础概念做了一些总结,并且再次引出了"代理调度运行"的概念。

本篇文章讲述kernel 7.1版本中的"代理调度运行"设计用意及相关功能。

代理调度运行(SCHED_PROXY_EXEC)

延迟出列(sched_delayed)

系列文章列表

代理调度运行(SCHED_PROXY_EXEC)

任务优先级反转从 1991 年 Linux 诞生之初、由于支持多任务和进程同步锁就原生存在的经典理论缺陷。举个经典的例子,高优先级任务被低优先级任务阻塞,导致中优先级任务比高优先级任务先执行的现象:

  1. 低优先级(任务A):如获取了共享内存的总线锁(互斥锁)。
  2. 高优先级(任务C):需要获取同一个总线锁,因此被挂起并等待任务A释放锁。
  3. 中优先级(任务B):它不需要锁,但它的优先级高于任务A,因此它抢占了任务A的CPU时间。

Linux 2.6.18 版本中,内核正式合入了 RT-Mutex(实时互斥锁)机制和 PI-Futex(优先级继承 Futex),当高优先级任务C阻塞于低优先级任务A持有的锁时,任务A临时提升为任务C的优先级,从而避免中等优先级的任务B抢占,让任务A快速执行完并释放锁。这首次在上游代码中预防了实时任务的ABC反转,但大部分服务器内核未开启/未使用RT-Mutex等机制(成本代价偏高,并且cfs基本调度类的任务还可以靠某个时刻检测,持锁顺延等手段),因此各家公司内部流传着自己的治理手段。

EEVDF到来的时代,新型服务器逻辑cpu数量已经达到512核心,更多的容器及任务数量,更复杂的迁移场景(如任务驱逐形式迁移,高优先级调度类任务频繁抢占等),任务优先级反转成为不可忽视并且持续演进的死锁问题。

7.0及以上版本中(kernel 6.17中增加),调度代理运行(SCHED_PROXY_EXEC)功能已经愈发稳定,执行逻辑如下(__schedule流程):

  1. 选取下一个任务。
  2. rq队列下一个调度类赋值为下一个任务调度类。
  3. rq队列贡献任务(donor)赋值为下一个任务。
  4. 下一任务属于阻塞状态,从贡献任务向互斥锁的所属者(owner)遍历(找出哪个任务拿到的互斥锁):
    4.1. 互斥锁没有所属者,任务锁阻塞状态清空(未持有互斥锁或者在非预期的互斥锁上阻塞则打印一次警告),贡献任务可以运行了,返回贡献任务。
    4.2. 所属者不在rq队列中或者所属者的调度实体支持延迟出列(sched_delayed),rq队列贡献任务赋值为rq队列空闲任务(互斥锁持有者偷懒了,贡献任务只能先放一放等互斥锁持有者让出锁了再说,并且当前只能让空闲任务运行避免锁过久等待,优先级反转等问题),设置重新调度标志并返回rq队列空闲任务。
    4.3. 所属者所在的cpu不是当前cpu,当前rq队列设置重新调度标志并返回rq队列空闲任务,将贡献任务迁移到所属者所在的cpu队列中(贡献任务在这里没啥用了,去所属者的cpu吧,等他让出锁就解放了。但是在7.0版本中还是上一个想法,贡献任务还是等互斥锁持有者让出锁了再说,说明7.1版本确实进化了,与其等待不如加入)。
    4.4. 所属者包含正在被迁移标志,设置重新调度标志并返回rq队列空闲任务(所属者也不保了,等他稳定了再说)。
    4.5. 所属者不在rq队列中或者所属者所在的cpu不是当前cpu,返回null(重试吧,所属者可能发生了变动)。
    4.6. 所属者是贡献任务,设置重新调度标志并返回rq队列空闲任务(???ttwu_runnable发力的时刻到了,调度rq->idle,以便ttwu_runnable()能够获取rq锁,并将所有者标记为运行状态)。
    4.7. 返回所属者(理想的场景,锁到擒来)。

上面的调度代理运行可以看出这个功能只为了一件事,就是当前待运行的任务没有拿到锁,必须想尽一切办法让所属者先运行并让出锁,这段期间cpu运行空闲任务浪费cpu也能接受(出现这种锁等待场景说明硬件也快到达处理瓶颈了),毕竟死锁代价远远大于等待时间。

延迟出列(sched_delayed)

配合代理调度运行(SCHED_PROXY_EXEC)出的功能,当任务因为互斥锁阻塞等待时不用移出队列(包含DEQUEUE_SLEEP标志,不包含延迟出列或出列限流标志,并且没有运行资格),再次执行入列函数时需要先移出队列再加回队列,更新cfs_rq队列负载等。更新调度实体虚拟滞后值时,在开启DELAY_ZERO的情况下,调度实体的虚拟滞后值最大为0,避免窃取运行机会(理论上已经运行了足够的时间)。

延迟出列包括以下几种重要信息:

  1. 尝试唤醒函数(ttwu)和__sched_fork函数检测到任务具有延迟出列(sched_delayed = 1)打印警告。
  2. 选取下一个任务时,cfs_rq队列的next具有延迟出列(sched_delayed = 1)打印警告。
  3. 再次入列(requeue_delayed_entity)不具有延迟出列(sched_delayed = 0)打印警告。
  4. cfs抢占函数中具有延迟出列(sched_delayed = 1)的任务不具备抢占能力。
  5. 任务具有延迟出列(sched_delayed = 1)时,cfs_rq队列的层级可运行数量不包括这个任务。

系列文章列表

《cfs调度类深入解刨------核心结构的用意》

《cfs调度类深入解刨------核心结构细节分析》

《cfs调度类深入解刨------最新内核细节分析1》

相关推荐
养海绵宝宝的小蜗14 分钟前
LVS(Linux Virtual Server)项目知识点总结
linux·运维·lvs
阿黎02141 小时前
Linux驱动
linux
tjjingpan1 小时前
HCIP-Datacom Core Technology V1.0_20 IPv6概述
linux·服务器·网络
云泽8081 小时前
Linux基础开发工具(三):Vim高级配置、Swap恢复机制与Sudo权限白名单详解
linux·运维·vim
qetfw2 小时前
CentOS 7 vsftpd.conf 配置文件详解:监听、用户、权限、被动模式与 TLS
linux·运维·centos·ftp·vsftpd
风曦Kisaki2 小时前
Kubernetes(K8s)笔记Day04:控制器(ReplicaSet 与Deployment),滚动更新及回滚,滚动更新策略,Pod 的 DNS 策略
linux·运维·笔记·docker·容器·kubernetes
code_whiter2 小时前
初阶linux2环境基础开发工具完整教程
linux
AmazingEgg2 小时前
RHCSA 第三天学习笔记
linux
数聚天成DeepSData2 小时前
外贸海关进出口数据去哪免费下载?从统计到明细的查找指南
linux·服务器·开发语言·前端·网络·人工智能·自然语言处理
Huangjin007_2 小时前
【Linux 系统篇(十)】基础开发工具(五) —— 第一个系统程序 - 进度条
linux·运维·服务器