OTHER CFS CLASS API

set_curr_task_fair(rq):将cpu运行队列里的当前运行进程设置为cfs运行队列里当前运行的进程(set_curr_task_fair),对于组调度则必须把它上级的se也设置为相应cfs_rq的当前运行进程。该接口主要用于修改某个进程的调度策略(__sched_setscheduler调度器类的运行队列信息也需要更新)或把一个进程从一个group迁移到另一个group的过程(__sched_move_task此时如果它是正在运行的,则需让它在新的group cfs_rq中也处于正在运行状态),注意:这里并不需要resched_task当前进程

switched_to_fair(rq, p, running):把rq里的进程p的调度策略切换到CFS。如果p是正在运行的,那么直接resched_task它;否则判断p是否能够抢占当前运行的进程。显然该接口也用于调度策略改变时调用(check_class_changed)

prio_changed_fair(rq, p, oldprio, running):该函数在p的优先级被改变时调用(在调度框架的__sched_setscheduler-à check_class_changed被调用)。如果p是正在运行的进程,并且它的优先级降低了,那么直接resched_task它,否则调用check_preempt_curr检查当前运行的是否该被p抢占(check_class_changed)

yield_task_fair(rq):该接口用于系统调用sched_yield中,这本身的逻辑非常简单:把当前进程从buddies中删除,并且更新它的执行时间update_curr,最后把它设置为skip_buddy(上面的pick_next_task我们说过如果是skip的话,在选择的时候会被skip的),这里及sched_yield系统调用并没有把当前进程设置为TIF_NEED_RESCHED,这是因为在sched_yield里直接调用了schedule,而不再需要在系统调用返回时去检查

yield_to_task_fair(rq, p, preempt):该函数不仅让当前进程让出CPU,而且想让p进程优先运行set_next_buddy,该接口用于yield_to函数中

CFS内部主要函数

__pick_first_entity(cfs_rq) :获得cfs_rq红黑树队列里最左边的节点

__pick_next_entity(se) :获得se所在红黑树的se的后一个节点

entity_key(cfs_rq, se) :se在cfs_rq的红黑树中的key,se->vruntime - cfs_rq->min_vruntime,这里使用这个差值为key(标准化后的),是因为vruntime本身为usigned long而且是一个递增的值, vruntime溢出了,那么就会导致顺序混乱,所以key不能直接使用vruntime,而这个差值就是为了防止溢出

update_min_vruntime(cfs_rq) :更新cfs_rq的min_vruntime,并且它保证每次将要更新的min_vruntime都大于等于当前的min_vruntime,即max(cfs_rq->min_vruntime,min(cfs_rq->curr->vruntime, cfs_rq->rb_leftmost->vruntime)),所以min_vruntime也是递增的

calc_delta_mine(delta_exec,weight, lw) :该函数用于计算物理delta_exec时间的相对时间,这个时间用delta_exec为基数 乘以 第二个参数与最后一个参数比重,即delta_exec * weight / lw.于是就有以下几种情况:
delta_exec为一个se实质运行的物理时间,第二个参数为NICE_0的权重,第三个参数为该se的本身权重:该函数计算出来的值就是该se它运行了delta_exec物理时间对应的虚拟时间,如calc_delta_fair;
delta_exec为一个运行队列的运行周期(物理时间),第二个参数为当前se的权重,第三个参数为运行队列本身的权重:该函数计算出来的值就是该se在当前运行队列中即将(理想)运行的物理时间,如sched_slice非组调度。

calc_delta_fair(delta,se): 计算se执行的delta物理时间的相应的虚拟时间

__sched_period(nr_running): 该函数用于计算当前运行队列所有se运行一遍所需要的时间周期,这是一个实质物理时间,当运行队列成员小于sched_nr_latency时,该时间为sysctl_sched_latency;否则等于 sysctl_sched_min_granularity *运行队列的成员个数(这个函数也是计算所谓的延迟调度周期,即内核保证在这么长的时间内它的运行队列的成员都会被执行至少一次,sysctl_sched_latency、sysctl_sched_min_granularity可以在 /proc/sys/kernel/ 上进行设置)

sched_slice(cfs_rq,se): 对于非组调度它计算的就是当前se在运行队列里所能分配的物理执行时间,首先计算出该队列的调度周期(__sched_period),然后按照该se在队列中所占的比重计算出它自己的理想执行时间__sched_period*(se->load/se->cfs_rq->load);对于组调度,它则算出该se对应的group root理想的物理执行时间。为什么要算到root?——假设我们有两个group并且它们的shares差一倍,但是它们下面的task load是一样的1024,那么它们的执行时间显然跟它们所属的group有关。即它的se的上级group se是这样计算的:parent_slice=child_slice*(parent_load/parent_cfs_rq->load)。注:如果se不在运行列队(从另一个cpu迁移过来),那么计算队列的load时还应该加上该运行的se的load。

__update_curr(cfs_rq,curr, delta_exec) :更新cfs_rq当前的运行se的累计物理执行时间sum_exec_runtime,vruntime(这里用到calc_delta_fair计算实质物理时间对应的虚拟时间)以及cfs_rq->min_vruntime(update_min_vruntime)

sched_vslice(cfs_rq,se) :计算该se理想情况下运行的物理时间相对应的虚拟时间

update_curr(cfs_rq) :该函数调用__update_curr更新vruntime,及更新一些统计信息

wakeup_gran :用于计算被抢占进程的最小执行时间(物理时间sysctl_sched_wakeup_granularity 1ms)的虚拟时间(calc_delta_fair)

wakeup_preempt_entity :该函数用于判断一个新的se是否应该抢占当前的curr,如果当前的虚拟执行时间小于等于(优先不抢占)新的vruntime,显然当前执行的时间更少,所以不应该被抢占(返回-1);否则,假设新的se可以抢占curr,那么它最少需要运行wakeup_gran虚拟时间(sysctl_sched_wakeup_granularity保证最少运行时间防止频繁切换),如果这个时间比当前多运行的时间小的话,那么说明被抢占后新的se运行后的vruntime还会比当前的vruntime还小,这样新的se可以抢占当前curr(返回1);0好像也表示不应该抢占

place_entity(cfs_rq,se, initial) :确定se被wakeup(initial=0)或者刚被fork的时新(initial=1)的合适vruntime,对于wakeup则进行适当的补偿(补偿因子sysctl_sched_latency,如果睡眠时间太短se->vruntime依然很大(比vruntime大),那么进程虚拟时间不变,而得不到奖励);对于刚被fork的进程,则把它的vruntime赋值为cfs_rq->min_vruntime,另外因为进程刚被创建,它的运行应当被放在运行周期之后,所以加上运行周期对应虚拟时间(sched_vslice)

set_next_entity(cfs_rq,se) :将se置为当前cfs_rq上正在运行的进程,如果它是在运行队列里,则先出队,否则直接cfs_rq->curr = se

set_last_buddy(se) :设置优先调度的last buddy

set_next_buddy(se) :设置优先调度的next buddy,它的优先级比last buddy高

set_skip_buddy(se) :设置不应该被调度的buddy,也就是它的优先级最最低

update_cfs_shares(cfs_rq) :更新该cfs_rq自身所属的se weight.load值(se = tg->se[cpu_of(rq_of(cfs_rq))]),新的shares值计算公式为:(tg->shares*cfs_rq->load.weight)/(tg->load_weight-cfs_rq->load_contribution+cfs_rq->load.weight),注意最后在更新时 reweight_entity (cfs_rq_of(se), se, shares),这时传给reweight_entity就是这个se所属的cfs_rq(上级的my_q),而不是它自己本身了,因为如果这个se已经在它的上级cfs_rq里,那么应该先减去它旧的shares值,然后再更新该se的shares值,然后再用新的se shares值加到这个上级cfs_rq里

account_entity_enqueue(cfs_rq,se) :入队列时相应更新,包括cfs_rq的load,nr_running;另外如果该se是root的话,则增加cfs_rq对应的rq的load,如果该se是task的话,则增加cfs_rq的task weight

account_entity_dequeue(cfs_rq,se) :做account_entity_enqueue的相反操作

reweight_entity(cfs_rq,se, weight) :重新计算se的load及相应的cfs_rq的load(如该se在cfs_rq里),即先把该se account_entity_dequeue,再更新se的load update_load_set,最后再重新计算cfs_rq的load account_entity_enqueue

版权声明:本文为博主原创文章,未经博主允许不得转载。

linux调度器(七)——other cfs class api and functions相关推荐

  1. Linux调度器及CFS调度器

    Linux调度器及CFS调度器 调度器 调度器类sched_class结构体 进程的优先级 调度策略 CFS调度器 实际运行时间 虚拟运行时间 调度器结构分析 调度器 ​ 调度:就算按照某种调度的算法 ...

  2. 【Linux 内核】CFS 调度器 ② ( CFS 调度器 “ 权重 “ 概念 | CFS 调度器调度实例 | 计算进程 “ 实际运行时间 “ )

    文章目录 一.CFS 调度器 " 权重 " 概念 二.CFS 调度器调度实例 ( 计算进程 " 实际运行时间 " ) 一.CFS 调度器 " 权重 & ...

  3. Linux 调度器发展简述

    引言 进程调度是操作系统的核心功能.调度器只是是调度过程中的一部分,进程调度是非常复杂的过程,需要多个系统协同工作完成.本文所关注的仅为调度器,它的主要工作是在所有 RUNNING 进程中选择最合适的 ...

  4. Linux调度器笔记

    相关资料 <linux 调度子系统>这个博客讲的非常好 <linux调度器源码分析 - 概述(一)>讲的也挺好,有源码分析. SCHED_FIFO等调度策略的定义和设置可以参考 ...

  5. 能感知功耗的Linux调度器(EAS)

    译者简介 白嘉庆,西邮陈莉君教授门下研一学生.曾在华为西安研究所任C++开发一职,目前兴趣是学习Linux内核网络安全相关内容. 本文的翻译宋宝华老师指导审阅. 序 2014年Linux内核峰会(Li ...

  6. Linux 调度器内幕

    内核中这个非常重要的组件的最新版本改进了可伸缩性 M. Jones 2006 年 9 月 07 日发布 WeiboGoogle+用电子邮件发送本页面 2 本文将回顾一下 Linux 2.6 的任务调度 ...

  7. 鼠眼看Linux调度器

    一.耗子 vs Linux ? "鼠目寸光",应该是个暴光率挺高的成语了,常用来说某人看事情没有深度,看不透本质.毫无疑问,这是一个贬义100%的词.但不管是认识什么未知事物,都一 ...

  8. 鼠眼看Linux调度器 by raise_sail @ chinaunix

    来源:http://my.chinaunix.net/space.php?uid=20043340&do=blog&id=154837 /* 这是一篇4年前的文章.本人最近学习linu ...

  9. linux cfs时间,Linux调度的实现(CFS)——虚拟时间计算

    公平调度(CFS)基本概念与性质 公平调度:每个进程能获得1/n的处理器时间,n指可运行的进程的数量: (允许每个进程运行一段时间,循环轮转,选择运行最少的进程作为下一个运行进程.) 每个进程都按照它 ...

  10. Linux进程里运行新代码,linux调度器源码分析 - 新进程加入(三)

    中专门描述了copy_process()这个创建函数,而里面有一个函数专门用于进程调度的初始化,就是sched_fork(),其代码如下 int sched_fork(unsigned long cl ...

最新文章

  1. Python之自动单元测试之一(unittest使用实例)
  2. [ImportNew]Java中的Timer类和TimerTask类
  3. rust(12)-闭包,闭包作为返回值,闭包作为参数
  4. 分析:新建短信,当我们接受人RecipientsEditor中输入+86的时候,系统会自己主动在+86后增加空格...
  5. 数字电子技术之逻辑函数的化简及表示
  6. autocad+服务器未响应,CAD图纸打开未响应解决的方法
  7. 在Mac里读取NTFS格式的盘
  8. python sklearn包中的主成分分析_九、Sklearn主成分分析
  9. vue3+vite中显示img图片,显示不出来问题。
  10. EastWave应用案例:同轴线仿真
  11. c#用串口传输二进制文件 xmodem协议
  12. 关于Untiy编写敌人可视化视野
  13. Linux:安装 telnet 命令
  14. js序列化与反序列化和C#中json序列化与反序列化
  15. java中文乱码问题
  16. html下拉框的选择和值传递
  17. Export常见的15种认证
  18. Android p2p局域网聊天软件的实现
  19. 从一个空白芯片开始制作arduino uno最小系统板
  20. discuz 7.2 /faq.php sql注入漏洞,Python写的Discuz7.2版faq.php注入漏洞工具

热门文章

  1. 台媒体:IBM PC将成特洛伊木马【ZZ】【另一个角度】
  2. android 点击屏幕 回调,Android 点击回调传递
  3. ZooKeeper 安装与部署
  4. python--练习--for i in range(2,101)
  5. docker 升级版本
  6. 正则表达式案例分析 (二)
  7. AppCan入门教程
  8. 项目管理-计划与实施,哪个更重要
  9. Utils工具方法集插件详解
  10. nexus build docker private registry