为什么Linux CFS不在Core2Duo中为运行队列的其他可用进程分配免费CPU?

时间:2018-12-11 18:51:44

标签: c linux timer cfs

我正在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之外的所有线程都处于阻塞状态(等待信号量)。

  1. T0执行一些任务,然后设置一个持续时间为2000纳秒的计时器,并自动释放CPU。由于没有可用的线程,因此安排了P2。
  2. 在2000纳秒之后,计时器到期,它唤醒立即抢占P2的下一个线程T1。
  3. T1执行一些任务,然后设置一个持续时间为2000纳秒的计时器并自动释放CPU。由于没有可用的线程,因此安排了P2。
  4. 在2000纳秒之后,计时器到期,它唤醒立即抢占P2的下一个线程T2。

这重复执行,线程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在这种情况下不选择下一个调度过程?

0 个答案:

没有答案