我一直在做一些实验来尝试理解基于ARM的嵌入式系统上的CFS调度程序。在测试中,当我在sched_fair.c中调整调度程序的参数时,我看不到行为的任何变化。我的理解是,在被抢占之前,进程应至少运行 sysctl_sched_min_granularity 。有没有人知道为什么我的线程比以下测试设置更长或更短的时间运行?
以下是sched_fair.c的相关更改
/*
* Targeted preemption latency for CPU-bound tasks:
* (default: 5ms * (1 + ilog(ncpus)), units: nanoseconds)
*/
unsigned int sysctl_sched_latency = 20000000ULL; /* Changed from 5ms to 20ms */
/*
* Minimal preemption granularity for CPU-bound tasks:
* (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds)
*/
unsigned int sysctl_sched_min_granularity = 4000000ULL; /* Changed from 1ms to 4ms */
/*
* SCHED_OTHER wake-up granularity.
* (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds)
*
* This option delays the preemption effects of decoupled workloads
* and reduces their over-scheduling. Synchronous workloads will still
* have immediate wakeup/sleep latencies.
*/
unsigned int sysctl_sched_wakeup_granularity = 4000000UL; /* Changed from 1ms to 4ms */
对于我的测试程序,我有一个休眠的线程,SLEEP_TIME_US定义了多长时间。
#define SLEEP_TIME_US 1000
' DoNothing'线程处于无限循环中:
static void *DoNothing(void *)
{
int i = 0;
while(true)
++i;
return NULL;
}
' SleepThread'坐在无限循环中并睡眠SLEEP_TIME_US设置的预定时间。
static void *SleepThread(void *)
{
int i = 0;
while (true)
{
++i;
usleep(SLEEP_TIME_US);
}
return NULL;
}
启动我的主题的函数:
void StartDoNothingThread()
{
pthread_t t;
pthread_create(&t, NULL, &DoNothing, NULL);
}
void StartSleepThread()
{
pthread_t t;
pthread_create(&t, NULL, &SleepThread, NULL);
}
实验:
int main(int argc, const char * argv[])
{
StartDoNothingThread();
StartDoNothingThread();
StartDoNothingThread();
StartDoNothingThread();
StartSleepThread();
clock_t startCycles = clock();
clock_t endCycles;
double cpuTime;
system("echo 0 > /sys/kernel/debug/tracing/tracing_enabled");
system("echo '' > /sys/kernel/debug/tracing/trace");
system("echo 1 > /sys/kernel/debug/tracing/tracing_enabled");
while (true)
{
endCycles = clock();
cpuTime = ((double)(endCycles - startCycles))/CLOCKS_PER_SEC;
if (cpuTime > 1) // Quit after 1 sec
{
system("echo 0 > /sys/kernel/debug/tracing/tracing_enabled");
return 0;
}
}
}
我可以使用pyTimeChart绘制ftrace的输出,它显示了上下文切换。我不完全理解的是调度程序早于/晚于 sysctl_sched_min_granularity 切换任务的原因。
当我 DON' T 运行睡眠线程时,通过注释掉StartSleepThread(),每个线程运行10ms。但是,根据我的调度程序设置,我假设每个任务都运行4ms。
当我运行sleep线程并将SLEEP_TIME_US设置为1000时,每个线程运行1ms。
当我运行sleep线程并将SLEEP_TIME_US设置为500时,每个线程运行0.5ms。
我注意到我的架构defconfig和调度中的CONFIG_HZ设置之间可能存在相互影响。我相信我正在运行无滴答内核。尽管我尝试将CONFIG_HZ设置为1000,但更改它似乎不会影响任何线程执行时间。目前我的CONFIG_HZ设置为100.如果我可以添加任何说明,请告诉我。
修改
通过更多的修补,我能够让我的内核每ms发一次。问题是Kconfig不包括Kconfig.hz。最后,事情变得更有意义了。例如,线程至少运行了shed_min_granularity并且sched_latency被尊重。
也就是说,直到我重新插入我的睡眠线程。当休眠线程正在运行时,调度程序将仅在睡眠期间运行任务,然后切换到下一个。这是在2.6.32。在较新的内核4.1上,即使使用休眠线程,任务也始终为min_granularity运行。由于其他原因我不习惯使用2.6.32,但我仍然希望了解这种差异。