Linux Scheduler之rt选核流程

前言
在linux中,有些线程需要被公平调度,保证每个线程不会长时间的调度不到,这就是我们熟知的cfs调度类(sched class),但是也有一些关键线程(比如一些显示刷帧的支撑线程),我们需要保证线程能够及时被调度到,针对普通负载较轻的场景,线程的调度及时性都能得到保证。但是为了满足人们的日常使用需求,操作系统后台驻留任务越来越多(这种现象在android设备上表现尤为严重),而系统的cpu始终只有一个,即使这个cpu有8个核甚至更多,cpu也有可能被塞满task,为了保证一些重要task的及时运行,这里就有了实时进程的概念。
linux中,系统是通过优先级来区分非实时线程和实时线程的,linux将线程优先级分为140个等级,从0~139,这个值越小其优先级越高,实时线程也叫rt(real time)线程,其优先级范围为[0,99],非实时线程为[100,139]。非实时线程也叫cfs线程,他的default优先级为120,通过nice值转化为最终的线程优先级。nice值的取值范围为-20~19,可以通过ps命令查看ni列:
本文主要讲述rt线程的选核流程。
rt选核流程介绍
每个task在被wakup唤醒时候都会从try_to_wake_up开始执行,这里会为task选择合适的cpu运行,其核心逻辑位于select_task_rq函数里面,它会根据task的sched_class确定调用的具体函数,而task的sched_class初始化则是在系统更改或者设置task的priority时,根据task的priority进行设置:
如果一个线程为rt,它的sched_class则为rt_sched_class,结构体初始化定义如下:
那么rt线程对应调度类的选核函数为select_task_rq_rt,其基本的执行逻辑如下图1:
图1
rt选核流程比较简单,其核心逻辑位于find_lowest_rq函数中,此函数主要用于寻找符合当前rt线程运行的cpu,其核心逻辑如下图2:
图2
cpupri_find_fitness负责从所有系统中所有的符合task运行条件的cpu找出来,并更新到lowest_mask里面,然后find_lowest_rq再从最终的lowest_mask里面选择合适的cpu,选择逻辑:
如果lowest_mask里面包含task的prev cpu,则直接选择prev cpu。
选择lowest_mask在task的sched domain里面的第一个cpu。
如果前面都没找到cpu,则判断lowest_mask里面是否包含了wake cpu,如果包含则直接返回wake cpu
最后如果都没找到,lowest又不为空,则从lowest_mask里面找一个随机的cpu返回。
下面来看下cpupri_find_fitness如何找到合适的所有适合task运行的cpu,主要分为3个部分:
1.首先对task优先级进行一个转化,将系统中的task分为0~102个等级,优先级由低到高,可以分为invalid,idle,normal和rt四类。
图3
其中invalid优先级为0,idle优先级为1,所有的cfs线程占用一类,优先级为2,rt则每个优先级占用一个等级。
2.因为rt线程是可以抢占的,for循环从最低优先级开始遍历,这里的优先级为已经转化为103个级别的优先级状态,其选核逻辑一般为首先选择idle的cpu运行,其次是抢占有cfs task的cpu运行,最后才会考虑取抢占其他低优先级rt task的cpu,通过__cpupri_find查找各个优先级在cpu上的运行状态,找到可以使用的cpu。cpupri_vec结构体有两个成员,count用来存储各个优先级task在哪些cpu上属于最高优先级task,mask则用来存储当前优先级所在cpu上是最高优先级的的cpumask。例如当前系统中cpu0~5上没有全是cfs task在运行,那么normal task的count值为6,mask为0x3f。
__cpupri_find的基本逻辑:
判断当前优先级在哪些cpu上是最高优先级,如果没有的话,说明当前系统要么没有此优先级task,要么是当前优先级task并非系统中各个cpu的最高优先级。
当前优先级task在有cpu是处于最高优先级,从这些cpu里面去除掉task not allowed cpu,再去除掉被isolation的cpu,最后如果lowest_mask还有cpu,则将lowest_mask作为后面选核的基础。
经过__cpupri_find找到lowest_mask后,再从lowest_mask里面过滤掉capacity无法满足当前task的cpu,最后剩下的就是可以用来运行当前task的cpumask,如果没有剩余,则说明当前优先级的task所运行的cpu没有满足条件的,此时需要进入下一个循环,找到更高优先级的task运行的cpu。
3.如果此次循环没有找到合适的cpu,会再进行一次循环,尝试找到合适的cpu。
至此,rt选核的整体流程介绍完毕。
结语
本文主要从代码的角度讲述了linux rt选核的主要流程,旨在让读者对于rt线程及其选核逻辑有一个初步的认识,利用rt线程的优点,可以解决当前系统中因为调度延迟引起的一些性能问题。
rt线程选核相对cfs线程而言要简单一些,他不会考虑energy等因素,但系统中过多的rt task可能会带来一定的功耗影响,同时由于rt主要是为了解决重要task的调度延迟问题,如果系统中过多的rt线程可能导致一些重负载场景可能所有cpu都是rt task,引发rt线程的调度延迟,从而导致更严重的性能问题,所以也不宜在系统中设置过多的rt task。


shell是什么?shell实现原理分析基于MM32 MCU的shell脚本源码
unix操作系统常用命令
航锦科技全资子公司获两大FPGA订单 实现了该类产品的国产化替代
一根数据线可以实现多少功能
使用MAX1253/54和MAX1153/54进行温度监测
Linux Scheduler之rt选核流程
石墨烯——知识需要分享
热继电器测试仪的原理
腾讯、阿里、网易等to C互联网巨头对to B市场从来都不只是观望而已
什么是智能家居网关,它的作用是什么
PLC现场实例电气原理图及编程
敦泰营收不断减少,根本原因是大陆智能手机市场呈现衰退趋势
FDD和WCDMA系统发射机的设计及性能分析
三星将扩大自家移动应用处理器搭载比重至60%
2022年中国汽车集团低碳化转型研究报告
电容式触摸屏的相关知识
具有线性线损补偿的USB 车载充电器参考设计
半导体应变计性能
剑指高端,看东芝电视如何凭借X9400 OLED旗舰突围?
基于Microblaze的LwIP以太网环境搭建