我正在探索 CFS 调度程序。根据 CFS,vruntime 是进程在 CPU 上运行的时间。因此,一旦一个进程消耗了一些 CPU,它的 vruntime 就会增加。
为了深入理解 context_switch 的概念,我研究了 kernel/sched/core.c 文件的 context_switch 方法实现。
context_switch(struct rq *rq, struct task_struct *prev,
struct task_struct *next)
要了解上下文切换所涉及的进程 - 特别是要知道哪个进程被调度出来以及哪个进程被调度进来,我添加了
trace_printk(KERN_INFO "**$$,traceme,%d,%llu,%llu,%d,%llu,%llu\n", (int)(prev->pid),prev->se.vruntime,prev->se.sum_exec_runtime, (int)(next->pid),next->se.vruntime,next->se.sum_exec_runtime);
在 kernel/sched/core.c 文件的 context_switch() 函数内部。
清理后的一些样本数据
//(prev->pid),prev->se.vruntime,prev->se.sum_exec_runtime, (int)(next->pid),next->se.vruntime,next->se.sum_exec_runtime
Line-1 : 7560,24498429469681,823155565,7566,24498418258892,1637962
Line-2 : 7566,24498418261234,1640304,7580,24498417733416,1018016
Line-3 : 7580,24498417752807,1037407,686,24498429468802,48339928895
Line-4 : 686,24498429469817,48339929910,7566,24498418261234,1640304
Line-5 : 7566,24498418263610,1642680,7581,24498417762357,1038126
Line-6 : 7581,24498417781339,1057108,7560,24498429469681,823155565
Line-7 : 7560,24498429470724,823156608,7566,24498418263610,1642680
Line-8 : 7566,24498418265980,1645050,7582,24498418395747,1202608
Line-9 : 7582,24498418414400,1221261,686,24498429469817,48339929910
Line-10: 686,24498429470804,48339930897,7566,24498418265980,1645050
Line-11: 7566,24498418268334,1647404,7583,24498417826636,1168325
Line-12: 7583,24498417845297,1186986,7560,24498429470724,823156608
Line-13: 7560,24498429471802,823157686,7566,24498418268334,1647404
Line-14: 7566,24498418270800,1649870,686,24498429470804,48339930897
// Up to this line vruntime of all process increased in each run as expected.
Line-15: 686,24498438028365,48348488458,7560,24498429471802,823157686
Line-16: 0,0,0,7,918077230457,2930949708
Line-17: 7,918077232097,2930951348,0,0,0
Line-18: 7560,6056741110796,823305719,7584,24498429478909,1156272 <---- Here vruntime of process 7560 is decreased . Why?
从上面的数据我们可以推断出每个进程在被调度之前执行了多少时间。
p_pid p_vrt p_sum_exe_rt n_pid n_vrt n_sum_exe_rt | prev_tslice next_tslice CPU
7560 , 24498429469681, 823155565, 7566 , 24498418258892, 1637962, | , 1191 , 2327
7566 , 24498418261234, 1640304, 7580 , 24498417733416, 1018016, | , 2342 , 19462
7580 , 24498417752807, 1037407, 686 , 24498429468802, 48339928895, | , 19391 , 1003
686 , 24498429469817, 48339929910, 7566 , 24498418261234, 1640304, | , 1015 , 2342
7566 , 24498418263610, 1642680, 7581 , 24498417762357, 1038126, | , 2376 , 18429
7581 , 24498417781339, 1057108, 7560 , 24498429469681, 823155565, | , 18982 , 1191
7560 , 24498429470724, 823156608, 7566 , 24498418263610, 1642680, | , 1043 , 2376
7566 , 24498418265980, 1645050, 7582 , 24498418395747, 1202608, | , 2370 , 19520
7582 , 24498418414400, 1221261, 686 , 24498429469817, 48339929910, | , 18653 , 1015
686 , 24498429470804, 48339930897, 7566 , 24498418265980, 1645050, | , 987 , 2370
7566 , 24498418268334, 1647404, 7583 , 24498417826636, 1168325, | , 2354 , 19617
7583 , 24498417845297, 1186986, 7560 , 24498429470724, 823156608, | , 18661 , 1043
7560 , 24498429471802, 823157686, 7566 , 24498418268334, 1647404, | , 1078 , 2354
7566 , 24498418270800, 1649870, 686 , 24498429470804, 48339930897, | , 2466 , 987
686 , 24498438028365, 48348488458, 7560 , 24498429471802, 823157686, | , 8557561 , 1078
//----------------------- Up to this line vruntime is increased
7560 , 6056741110796, 823305719, 7584 , 24498429478909, 1156272, | , 148033 , 18671
一切看起来都很完美 - 每次运行都会增加进程的 vruntime。
令我惊讶的是,在最后一行中,正在运行的进程的 vruntime 减少了。
pid 7560 进程的 vruntime 在最后一行减少(从 24498429471802 到 6056741110796) - 为什么?
即使进程被固定到特定的 CPU 核心(因此没有机会迁移到其他 CPU 核心),如何减少正在运行的进程的 vruntime?
- 另一个重要的观察结果是,在其他运行 7560 进程中运行的时间片较短,但最后一次它获得了更高的时间片。更大的时间片和减少 vruntime 之间有什么关联吗?
我正在使用 Debian 8.0 和 Ubuntu 16.04,内核 3.16.35,这在两个操作系统中都发生了。
任何了解原因的链接都会有很大帮助。