CFS调度算法:摒弃固定时间片,采用进程权重值的比重来量化计算实际运行时间,并引入虚拟时间和真实时间的概念,真实时间就是在物理时钟下实际运行的时间,虚拟时间是实际运行时间与nice值为0对应的权值的比值。
虚拟时间片引入:假设进程不存在优先级区分,那么只要保证每个进程的实际运行时间相同即可,能做到绝对公平。调度时,调度器只需要记录每个进程的实际时间,每次调度时挑出【已经运行时间最短的进程】。
然而事实上每个进程会涉及不同的优先级,此时不同的进程应该由于优先级的原因导致【真实运行时间的所占权重】不同才行,那么如何评估进程运行时间的长短?如何选择下一个进程进行调度?
由此引入虚拟运行时间【希望不同的进程根据优先级在一个调度延迟【调度延迟就是保证每一个可运行进程都至少运行一次的时间间隔】内分配的物理时间通过一个公式计算得到一个相同的值,称这个值为虚拟时间】,当选择下一个进程执行的时候,找出虚拟时间最小的进程即可。虚拟时间要保证优先级高的进程的虚拟时间过得慢一些,优先级低的进程的虚拟时间快一些。
引入虚拟运行时间,CFS中就绪队列使用一棵以虚拟时间为键的红黑树将调度实体组织起来,利用红黑树的特性,虚拟时间最短的进程在红黑树的最左端,调度器每次选择位于红黑树最左端的虚拟时间对应的调度实体参与调度。
如下所示,通过cat/proc/$pid/sched查看某个进程调度信息,第二行se.vruntime就是虚拟运行时间:
由上面的展示也可以看出来调度相关的这些信息是存储在调度实体se中,【每个进程描述符中都有每种调度类对应的调度实体,调度实体存放与该调度类相关的调度信息,并参与调度,CFS调度器对应的调度实体为struct sched_entity se,例如实时调度器对应的调度实体为struct sched_rt_entity rt】,CFS调度器的调度实体如下:
struct sched_entity
{
struct load_weight load; /* for load-balancing负荷权重,这个决定了进程在CPU上的运行时间和被调度次数 */
struct rb_node run_node;
unsigned int on_rq; /* 是否在就绪队列上 */
u64 exec_start; /* 上次启动的时间*/
u64 sum_exec_runtime;
u64 vruntime; /* 虚拟运行时间*/
u64 prev_sum_exec_runtime;
/* rq on which this entity is (to be) queued: */
struct cfs_rq *cfs_rq;
...
};
虚拟运行时间的计算关于tick:tick是周期性的时钟中断,时钟中断驱动调度器runing,其周期间隔根据硬件频率的设定相关(T=1/f),如下:
T=1/250 = 4ms,也就说时钟中断以4ms为周期【tips:每发生一次时钟中断,jiffies的数值就加上1】,每一个进程的虚拟时间在时钟中断里面被维护,每次时钟中断都要更新当前进程的虚拟时间。更新调用的主要函数如下:
static void update_curr(struct cfs_rq *cfs_rq)
{
struct sched_entity *curr = cfs_rq->curr;
u64 now = rq_clock_task(rq_of(cfs_rq));
u64 delta_exec;
if (unlikely(!curr))
return;
delta_exec = now - curr->exec_start;
if (unlikely((s64)delta_exec <= 0))
return;
curr->exec_start = now;
schedstat_set(curr->statistics.exec_max,
max(delta_exec, curr->statistics.exec_max));
curr->sum_exec_runtime += delta_exec;
schedstat_add(cfs_rq->exec_clock, delta_exec);
curr->vruntime += calc_delta_fair(delta_exec, curr);
update_min_vruntime(cfs_rq);
if (entity_is_task(curr)) {
struct task_struct *curtask = task_of(curr);
trace_sched_stat_runtime(curtask, delta_exec, curr->vruntime);
cgroup_account_cputime(curtask, delta_exec);
account_group_exec_runtime(curtask, delta_exec);
}
account_cfs_rq_runtime(cfs_rq, delta_exec);
}
代码逻辑比较简单:1、确定就绪队列的当前执行的调度实体
/* 确定就绪队列的当前执行进程curr */
struct sched_entity *curr = cfs_rq->curr;
2、根据获取的当前执行进程,计算当前和上一次更新负荷权重时两次的时间的差值
u64 now = rq_clock_task(rq_of(cfs_rq));
u64 delta_exec;
if (unlikely(!curr))
return;
delta_exec = now - curr->exec_start;
if (unlikely((s64)delta_exec <= 0))
return;
3、重新更新启动时间exec_start为now,以备下次计算时使用,最后将计算出的时间差加到先前的统计时间上。
/* 重新更新启动时间exec_start为now */
curr->exec_start = now;
schedstat_set(curr->statistics.exec_max,
max(delta_exec, curr->statistics.exec_max));
/* 将时间差加到先前统计的时间即可 */
curr->sum_exec_runtime += delta_exec;
schedstat_add(cfs_rq, exec_clock, delta_exec);
这也是通过cat /proc/$pid/sched看到的一些统计信息 4、开始计算虚拟时间
curr->vruntime += calc_delta_fair(delta_exec, curr);
5、计算虚拟时间函数calc_delta_fair如下,忽略舍入和溢出检查,calc_delta_fair函数所做的计算如下:
/*
* delta /= w
*/
static inline u64 calc_delta_fair(u64 delta, struct sched_entity *se)
{
if (unlikely(se->load.weight != NICE_0_LOAD))
delta = __calc_delta(delta, NICE_0_LOAD, &se->load);
return delta;
}
其中NICE_0_LOAD的值为:1024,当进程的nice=0时,不需要进行加权处理,其虚拟时间就等于其实际运行时间。
# define SCHED_FIXEDPOINT_SHIFT 10
#define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT)
#define NICE_0_LOAD (1L << NICE_0_LOAD_SHIFT)
1024也就是Nice值为0对应的权重值,权重值在内核中是预先定义好的,如下所示:
const int sched_prio_to_weight[40] = {
/* -20 */ 88761, 71755, 56483, 46273, 36291,
/* -15 */ 29154, 23254, 18705, 14949, 11916,
/* -10 */ 9548, 7620, 6100, 4904, 3906,
/* -5 */ 3121, 2501, 1991, 1586, 1277,
/* 0 */ 1024, 820, 655, 526, 423,
/* 5 */ 335, 272, 215, 172, 137,
/* 10 */ 110, 87, 70, 56, 45,
/* 15 */ 36, 29, 23, 18, 15,
};
通过公式和内核预先设定的权重表,可以看出来:
Nice值越高(对应的优先级越低),权重越小,虚拟时间累加的越快(虚拟时间过得越快),Nice值越低(对应的优先级越高),权值越高,虚拟时间累加的越慢(虚拟时间过得越慢)。CFS的思想核心也就是这样,让每个调度实体的虚拟时间增加速度不同,使用虚拟时间来衡量调度实体在CPU上已经执行的时间。
总结: 不同优先级的进程以各自对应的速度推进虚拟时间,只要保证在一个调度延迟内虚拟时间的推进进展相同,就实现了完成公平,公平指的是相对公平,即按进程的权重给予不同的运行时间,虚拟时间越小,代表着受到了"不公平"对待,因此下一个参与调度的调度实体就是红黑树中的最左边(虚拟时间最小)的节点,如此一来既能公平选择进程,又能保证高权重进程获得较多的运行时间。关于虚拟时间还有很多其他关键点,如新加入的进程的虚拟时间如何设定、长时间阻塞或者睡眠的进程被唤醒时虚拟时间如何设定等等,将在以后的文章分析。
参考:
1 、http://www.wowotech.net/process_management/452.html
2 、https://cloud.tencent.com/developer/article/1371674?from=15425
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/TPMlYIsdr1uPixEoXI89nw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。