Linux内核共有三种调度算法,他们分别是:
1、SCHED_OTHER 分时调度策略,
2、SCHED_FIFO实时调度策略,先到先服务
3、SCHED_RR实时调度策略,时间片轮转
其中,SCHED_FIFO与SCHED_RR属于实时策略,SCHED_OTHER属于分时策略。
实时策略线程将得到优先调用,实时策略线程根据实时优先级决定调度权值,分时策略线程则通过nice和counter值决定权值,nice越小,counter越大,被调度的概率越大,也就是曾经使用了cpu最少的线程将会得到优先调度。
SCHED_OTHER 分时调度策略:
非实时的,无法设置优先级
SCHED_FIFO实时调度策略:
先到先服务。一旦占用cpu则一直运行。一直运行直到有更高优先级任务到达或自己放弃
SCHED_RR实时调度策略:
时间片轮转。当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。放在队列尾保证了所有具有相同优先级的RR任务的调度公平
所有任务都采用linux分时调度策略(SCHED_OTHER)时:
创建时指定优先级nice值,根据nice值确定在cpu上的执行时间(counter),对每个任务动态优先级的计算(counter+20-nice)结果去选择运行,当这 个时间片用完后(counter减至0)或者主动放弃cpu时,该任务被放在就绪队列末尾(时间片用完)或等待队列(因等待资源而放弃cpu)中。
所有任务都采用FIFO时:
优先级高的先运行,并且该任务将一直占有CPU直到优先级更高的任务就绪或者主动放弃。同优先级先入队列先运行。
所有任务都采用RR时
综合了前两种策略,优先级高的先运行,优先级相同共分时间片,用完时间片的去就绪队列尾。
任务中同时含有实时和分时时
当实时进程准备就绪后,如果当前cpu正在运行非实时进程,则实时进程立即抢占非实时进程。
主要目的时测试在不同的调度策略以及不同的优先级设定的状况下,线程的抢占情况。
测试方法主要为在设定线程策略与优先级后,创建三个线程,观察它们的log输出情况以及使用busybox top查看CPU占用情况。
修改线程属性的代码部分如下:
param1.sched_priority = 40; //修改优先级
pthread_attr_setinheritsched(&attr1,PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr1,SCHED_FIFO); //修改调度策略
if(0!=pthread_attr_setschedparam(&attr1,¶m1))
{
printf("setschedpolicy attr1 NG! \n");
}
实验全部代码:
#include
#include
#include
#include
#include
#include
#include
#if 1
void *Thread1(void* pp)
{
sleep(1);
int i;
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(),&policy,¶m);
switch(policy)
{
case SCHED_OTHER:
printf("SCHED_OTHER 1\n");
break;
case SCHED_RR:
printf("SCHED_RR 1 \n");
break;
case SCHED_FIFO:
printf("SCHED_FIFO 1\n");
break;
}
while(1)
{
for(i=1;i<5000000;i++)
{
}
printf("Pthread 1\n");
//usleep(500);
}
printf("Pthread 1 exit\n");
}
void *Thread2(void* pp)
{
sleep(2);
int i;
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(),&policy,¶m);
switch(policy)
{
case SCHED_OTHER:
printf("SCHED_OTHER 2\n");
break;
case SCHED_RR:
printf("SCHED_RR 2 \n");
break;
case SCHED_FIFO:
printf("SCHED_FIFO 2\n");
break;
}
while(1)
{
for(i=1;i<5000000;i++)
{
}
printf("Pthread 2\n");
//usleep(500);
}
printf("Pthread 2 exit\n");
}
void *Thread3(void* pp)
{
sleep(3);
int i;
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(),&policy,¶m);
switch(policy)
{
case SCHED_OTHER:
printf("SCHED_OTHER 3\n");
break;
case SCHED_RR:
printf("SCHED_RR 3 \n");
break;
case SCHED_FIFO:
printf("SCHED_FIFO 3\n");
break;
}
while(1)
{
for(i=1;i<5000000;i++)
{
}
printf("Pthread 3\n");
//usleep(500);
}
printf("Pthread 3 exit\n");
}
#endif
int main()
{
int uid;
uid = getuid();
if(uid==0)
printf("The current user is root\n");
else
printf("The current user is not root\n");
pthread_t ppid1,ppid2,ppid3;
struct sched_param param1;
struct sched_param param2;
struct sched_param param3;
pthread_attr_t attr1,attr2,attr3;
pthread_attr_init(&attr1);
pthread_attr_init(&attr2);
pthread_attr_init(&attr3);
param1.sched_priority = 40;
pthread_attr_setinheritsched(&attr1,PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr1,SCHED_OTHER);
if(0!=pthread_attr_setschedparam(&attr1,¶m1))
{
printf("setschedpolicy attr1 NG! \n");
}
param2.sched_priority = 20;
pthread_attr_setinheritsched(&attr2,PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr2,SCHED_RR);
pthread_attr_setschedparam(&attr2,¶m2);
if(0!=pthread_attr_setschedparam(&attr2,¶m2))
{
printf("setschedpolicy attr2 NG! \n");
}
param3.sched_priority = 20;
pthread_attr_setinheritsched(&attr3,PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr3,SCHED_RR);
pthread_attr_setschedparam(&attr3,¶m3);
if(0!=pthread_attr_setschedparam(&attr3,¶m3))
{
printf("setschedpolicy attr3 NG! \n");
}
pthread_create(&ppid1,&attr1,Thread1,NULL);
pthread_create(&ppid2,&attr2,Thread2,NULL);
pthread_create(&ppid3,&attr3,Thread3,NULL);
pthread_join(ppid1,NULL);
pthread_join(ppid2,NULL);
pthread_join(ppid3,NULL);
//while(1) {
//sleep(100);
//printf("main loop\n");
//}
pthread_attr_destroy(&attr1);
pthread_attr_destroy(&attr2);
pthread_attr_destroy(&attr3);
return 0;
}
创建三个分时线程:
因分时策略不能设置优先级,所以不进行优先级不同的测试。
实验结果如下:
创建三个实时FIFO线程,且它们三个的优先级相同,皆为30。
实验结果如下:
创建三个实时RR线程:
且它们三个的优先级相同,皆为30。
实验结果如下:
实验结论:
1、三种调度策略线程满足自身策略特性。
2、实时线程无条件抢占分时线程,分时线程无法抢占实时线程。
3、实时线程中,高优先级线程抢占低优先级线程。
4、实时线程中,高优先级线程运行中不会被低优先级线程所打断。
实验课题(以下说明并未在实验中测出):
linux有一个组策略就是分配实时和分时的时间片
sysctl -n kernel.sched_rt_period_us # 实时进程调度的单位CPU时间 1 秒
1000000
sysctl -n kernel.sched_rt_runtime_us # 实时进程在 1 秒中实际占用的CPU时间, 0.95秒
950000
这个设置说明实时进程在运行时并不是完全占用CPU的, 每1秒中有0.05秒的时间可以给其它进程运行.
这样既不会对实时进程的响应时间造成太大的影响, 也避免了实时进程卡住时导致整个系统无响应.