极简cfs公平调度算法

3.1 名词解释
|
全称
|
说明
|
|
| se | schedule entity | 调度实例,可以是一个task,也可以是一个group(当使用组调度时),linux支持组调度后,将调度实例从原来的task,抽象为se |
| rq | run queue | cpu的运行队列,每个cpu一个,处于Ready状态的se挂在对应的cpu运行队列上后,才会被选择投入运行 |
| cfs_rq | cfs rq | 公平调度运行队列,因为一般进程都是用cfs调度算法,一般进程的se都是挂在rq.cfs_rq上的 |
| vruntime | virtual runtime | se的一个重要成员,记录调度实例的cpu运行时长,schedule时,cfs调度每次都选取vruntime最小的se投入运行,这就是cfs调度算法的核心原理 |
struct sched_entity
{
unsigned int on_rq; // se是否在rq上,不在的话即使task是Ready状态也不会投入运行的
u64 vruntime; // cpu运行时长,cfs调度算法总是选择该值最小的se投入运行
}; struct task
{
struct sched_entity se; // 调度实例
}; struct rq
{
struct cfs_rq cfs; // 所有要调度的se都挂在cfs rq中
struct task_struct* curr; // 当前cpu上运行的task
}; struct cfs_rq
{
struct rb_root tasks_timeline; // 以vruntime为key,se为value的红黑树根节点,schedule时,cfs调度算法每次从这里挑选vruntime最小的se投入运行
struct rb_node* rb_leftmost; // tasks_timeline红黑树最左的叶子节点,即vruntime最小的se,直接取这个节点以加快速度
sched_entity* curr; // cfs_rq中当前正在运行的se
struct rq* rq; /* cpu runqueue to which this cfs_rq is attached */
unsigned int nr_running; // cfs_rq队列上有多少个se
};

entity_tick()
{
update_curr();
// 如果当前cfs_rq上的se大于1,则检查是否要重新调度
if (cfs_rq->nr_running > 1)
check_preempt_tick(cfs_rq, curr);
}
2> update_curr()主要是++当前task se的vruntime(当然这里还对组调度进行了处理,这里不讲组调度,先略过)
void update_curr(struct cfs_rq* cfs_rq)
{
struct sched_entity* curr = cfs_rq->curr;
curr->vruntime += delta_exec; // 增加se的运行时间
}
3> check_preempt_tick()判定当前运行的时间大于sched_slice时,即超过了时间片,或者其vruntime比当前cpu rq队列中最小的vruntime task大一个时间片,就会标记resched,然后等中断返回后会调用schedule()进行task切换
void check_preempt_tick()
{
// 如果运行时间大于sched_slice,则resched
if (delta_exec > ideal_runtime)
resched_task(rq_of(cfs_rq)->curr); // 如果比最小vruntime大一个sched_slice,则resched
se = __pick_first_entity(cfs_rq); // 选择cfs.rb_leftmost的se,即vruntime最小的se
delta = curr->vruntime - se->vruntime;
if (delta > ideal_runtime)
resched_task(rq_of(cfs_rq)->curr);
}
4> resched_curr()非常简单,就是设置一个resched标记位TIF_NEED_RESCHED
void resched_curr(struct rq* rq)
{
struct task_struct* curr = rq->curr;
set_tsk_thread_flag(curr, TIF_NEED_RESCHED);
}
void schedule()
{
prev = rq->curr;
put_prev_task_fair(rq, prev); // 对当前task进行处理,如果该task属于一个group,还要对组调度进行处理,这里不展开
// 选择下一个task并切换运行
next = pick_next_task(rq); // 选择一个vruntime最小的task进行调度
context_switch(rq, prev, next);
}
2> pick_next_task() → pick_next_task_fair() → pick_next_entity() → __pick_first_entity(),__pick_first_entity()选择vruntime最小的cfs_rq->rb_leftmost节点se进行调度
struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
{
struct rb_node *left = cfs_rq->rb_leftmost;
return rb_entry(left, struct sched_entity, run_node);
}
极简cfs公平调度算法的更多相关文章
- 基于Linux-3.9.4的mykernel实验环境的极简内核分析
382 + 原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ 一.实验环境 win10 -> VMware -> Ubuntu1 ...
- 【转帖】极简Docker和Kubernetes发展史
极简Docker和Kubernetes发展史 https://www.cnblogs.com/chenqionghe/p/11454248.html 2013年 Docker项目开源 2013年,以A ...
- CSharpGL(28)得到高精度可定制字形贴图的极简方法
CSharpGL(28)得到高精度可定制字形贴图的极简方法 回顾 以前我用SharpFont实现了解析TTF文件从而获取字形贴图的功能,并最终实现了用OpenGL渲染文字. 使用SharpFont,美 ...
- Vim,极简使用教程,让你瞬间脱离键鼠切换的痛苦
注:看大家对Vim仇恨极大,其实它只是一种文本操作方式,可以减少键鼠的切换,从而让编辑文本的操作更迅捷.并不等同于IDE,在我看来,它们是两个是包含关系,IDE可以有Vim编辑模式.Vim或许可以通过 ...
- CentOS下使用Postfix + Dovecot + Dnsmasq搭建极简局域网邮件系统
背景 开发环境为局域网,工作内容需要经常查看邮件文件(*.eml),可恶的Foxmail必须验证账户才能进入主界面,才能打开eml文件查看. 无奈搭一个局域网内的邮件系统吧.极简搭建,仅用于通过Fox ...
- 在Web应用中接入微信支付的流程之极简清晰版
在Web应用中接入微信支付的流程之极简清晰版 背景: 在Web应用中接入微信支付,我以为只是调用几个API稍作调试即可. 没想到微信的API和官方文档里隐坑无数,致我抱着怀疑人生的心情悲愤踩遍了丫们布 ...
- Snabbt.js – 极简的 JavaScript 动画库
Snabbt.js 是一个简约的 JavaScript 动画库.它会平移,旋转,缩放,倾斜和调整你的元素.通过矩阵乘法运算,变换等可以任何你想要的方式进行组合.最终的结果通过 CSS3 变换矩阵设置. ...
- 在Web应用中接入微信支付的流程之极简清晰版 (转)
在Web应用中接入微信支付的流程之极简清晰版 背景: 在Web应用中接入微信支付,我以为只是调用几个API稍作调试即可. 没想到微信的API和官方文档里隐坑无数,致我抱着怀疑人生的心情悲愤踩遍了丫们布 ...
- 基于 Node.js 平台,快速、开放、极简的 web 开发框架。
资料地址:http://www.expressjs.com.cn/ Express 基于 Node.js 平台,快速.开放.极简的 web 开发框架. $ npm install express -- ...
- HTML5播放器FlowPlayer的极简风格效果
在线演示 本地下载 使用Flowplayer生成的极简风格的播放器效果.
随机推荐
- Eclipse离线安装svn插件下载
site-1.4.8.zip site-1.6.18.zip site-1.8.22.zip site-1.10.9.zip site-1.10.13-1.9.x.zip site-1.10.13-1 ...
- [整理]String用法/转换substring
substring(a)从a开始 substring(a,b) [a,b] s=123456789 s.substring(3):456789 s.substring(0,3):1234
- JS实现10进制和26进制的转换
转载:https://blog.csdn.net/quentain/article/details/52803891 //将26进制转10进制 var ConvertNum = function (s ...
- RF射频的定义和原理
转自:http://www.saiyuan.net/portal/article/index/id/119/cid/28.html RF射频的定义和原理 定义 简称RF射频就是射频电流,它是一种高频交 ...
- 使用python来搭建一个简易的文件下载环境以及用droopy来实现一个文件上传环境
ubuntu在安装的时候一般都是自带python环境的,大家可以查看一下查看demo如下 用于共享的命令很简单python2: python -m SimpleHTTPServer 8888pytho ...
- LVS负载均衡 2022年4月
1. 负载均衡技术简介 2 1.1 负载均衡类型3 1.2 LVS简介4 1.3 Keepalived简介5 2. 负载均衡搭建主要步骤 6 2.1 LVS+Keepalived的负载均衡系统搭建6 ...
- [picoCTF]Scavenger Hunt write up
http://mercury.picoctf.net:5080/,这个网站周围隐藏着一些有趣的信息.你能找到它吗? 根据提示: 您应该有足够的提示来查找文件,不要运行暴力破解程序. 点击链接,进入页面 ...
- STM32的USART的DMA不定长度收发代码
/* * 函数名:USART1_DMA_Config * 描述 :串口1的DMA 的初始化配置 * 输入 :无 * 输出 : 无 * 调用 :在USART1_INIT()中被调用 */ voi ...
- Django视图中的请求与响应
一 请求 一 限制http请求 视图中的request,实际上是django源码中的HTTPRequest的子类WSGIRequest类的实例对象,主要由django对客户端请求的http协议报文进行 ...
- Android笔记--事务处理+数据库版本升级
事务处理 beginTransaction:开始事务的标志 setTransactionSuccessful:事务成功的标志 endTransaction:结束事务的标志 在上面的图片里面,首先进行事 ...