采用CFS调度算法的Linux内核中获取进程时间片长度

Linux内核2.6.23版本开始采用CFS(Completely Fair Scheduler)调度器,但开发者没有什么方便的办法获取进程的时间片长度,这里介绍一种通过修改Linux内核源码的方式,方便地在用户空间获取进程的时间片长度. 实验的Linux内核版本是4.4.154.

定义模块参数

首先在/usr/src/linux-4.4.154/kernel/sched/core.c中定义两个模块参数.

1
2
3
4
5
6
7
8
9
// added by szh
#include <linux/time.h>
int enable_flag = 0;
int enable_pid = -1;
module_param(enable_flag, int, 0664);
module_param(enable_pid, int, 0664);
EXPORT_SYMBOL_GPL(enable_flag);
EXPORT_SYMBOL_GPL(enable_pid);
// end

enable_flag表示是否输出进程的时间片长度,1表示输出,0表示不输出.

enable_pid表示pid等于enable_pid值的进程的时间片长度将被输出.

可以在用户空间通过/sys/module/core/parameters/enable_flag/sys/module/core/parameters/enable_pid来修改参数的值.

添加计算时间片长度的代码

/usr/src/linux-4.4.154/kernel/sched/core.c中,添加以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static void __sched notrace __schedule(bool preempt)
{
...
// added by szh
do_gettimeofday(&(next->__ts));
next->__start_ts = (next->__ts).tv_sec * 1000000 + (next->__ts).tv_usec;
prev->__end_ts = next->__start_ts;
if (enable_flag == 1 && prev->pid == enable_pid) {
printk(KERN_INFO "%d\n", prev->__end_ts - prev->__start_ts);
}
// end
rq = context_switch(rq, prev, next); /* unlocks the rq */
...
}

当内核从进程A到进程B进行上下文切换前,我们需要获取进程B的起始时间作为进程A的结束时间,进程A的结束时间减去进程A的起始时间,就是进程A的时间片长度,单位是微秒.

修改task_struct

在Linux内核中,进程描述符task_struct包含了进程所需的全部信息. 根据上述计算时间片长度的代码,我们需要修改/usr/src/linux-4.4.154/include/linux/sched.h,添加三个变量:

1
2
3
4
5
6
7
8
9
struct task_struct {
// added by szh
struct timeval __ts;
int __start_ts;
int __end_ts;
//end
...
}

重新编译内核

重新编译内核使修改生效,将enable_flag值改为1 (sudo sh -c “echo 1 > /sys/module/core/parameters/enable_flag”),将enable_pid值改为需要输出时间片长度的进程的PID (sudo sh -c “echo PID > /sys/module/core/parameters/enable_pid”),通过dmesg命令即可查看输出的时间片长度.

参考

The length of timeslices for processes under CFS process scheduling algorithm in Linux Kernel


版权声明

作者:萝卜姓胡
许可协议:Creative Commons Attribution-ShareAlike 4.0 International License
本文永久链接:http://hw2007.com/2018/10/03/采用CFS调度算法的Linux内核中获取进程时间片长度/