我正在Core2Duo,2.20GHz系统中工作,该系统具有Ubuntu-12.04 OS,3.18.26内核。
我在Linux内核源代码中做了一些更改。
要获得上下文切换中涉及的所有进程(已调度和已调度),我在内核(kernel / sched / core.c)中进行了更改,并在context_switch函数内部添加了以下print语句。
trace_printk(KERN_INFO
"**$$,context_switch,%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);`
我正在同一CPU内核中运行两个不同的进程P1(具有100个线程-T0,T1,...,T99)和P2。 P2已经运行了很长时间,因此它的vruntime很高。
在P1内,创建了前100个线程,除T0之外的所有线程都处于阻塞状态(等待信号量)。
这重复执行,线程T0,T1,... T99以循环方式执行。
所以,执行顺序如下
T0-P2-T1-P2-T2-P2-T3-......T99-P2-T0-P2.....
我的实验结果表明
当我将计时器间隔设置为1800纳秒时,P2进程的平均时间为1450纳秒。
当我将计时器间隔设置为2000纳秒时,P2进程平均达到1600纳秒。
当我将计时器间隔设置为2500纳秒时,P2进程的平均时间为2050纳秒。
当我将计时器间隔设置为3000纳秒时,P2进程的平均时间为2600纳秒。
因此,我得出结论,在我的Core2Duo系统中,上下文切换时间约为350-450ns。我说的对吗?
另一项观察结果是,当我将计时器间隔设置为1600纳秒或1700纳秒时,尽管CPU是空闲的,但P2进程并未在两个线程之间进行调度-这意味着CPU在1200 -1300 nano左右变为空闲尽管P2处于就绪队列中,但仍可以运行。为什么会这样?
这是我的代码段:
// Program - P2
int main(int argc, char *argv[])
{
cpu_set_t my_set;
CPU_ZERO(&my_set);
CPU_SET(1, &my_set);
sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
while(1){
// does some task
}
}
// Program - P1
// timer handler awakening next thread
static void handler(int sig, siginfo_t *si, void *uc)
{
thread_no++;
ret = sem_post(&sem[(thread_no)%NUM_THREADS]);
if (ret)
{
printf("Error in Sem Post\n");
}
}
void *threadA(void *data_)
{
int turn = (intptr_t)data_;
cpu_set_t my_set;
CPU_ZERO(&my_set);
CPU_SET(1, &my_set);
sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
while(1)
{
ret = sem_wait(&sem[turn]);
if (ret)
{
printf("Error in Sem Post\n");
}
// does some work here
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = DELAY1;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
ret = timer_settime(timerid, 0, &its, NULL);
if ( ret < 0 )
perror("timer_settime");
}
}
int main(int argc, char *argv[])
{
sa.sa_flags = SA_RESTART;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
err = sigaction(SIG, &sa, NULL);
if (0 != err) {
printf("sigaction failed\n"); }
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
ret = timer_create(CLOCKID, &sev, &timerid);
if ( ret < 0 )
perror("timer_create");
sem_init(&sem[0], 0, 1);
for ( i = 1; i < NUM_THREADS; ++i)
{
sem_init(&sem[i], 0, 0);
}
data=0;
while(data < NUM_THREADS)
{
//create our threads
err = pthread_create(&tid[data], NULL, threadA, (void *)(intptr_t)data);
if(err != 0)
printf("\n can't create thread :[%s]", strerror(err));
data++;
}
}
内核跟踪显示, CPU空闲,有足够的时间用于上下文切换-线程Ti至P2,仍未调度P2,以后的上下文切换发生在Ti与T(i + 1)之间。 在计时器持续时间少于1700纳秒的情况下,为什么Linux CFS在这种情况下不选择下一个调度过程?