关于linux调度策略的学习总结

关于linux调度策略的学习总结


——————————————————————————————————


这里只做出出一些遇到问题的总结,对应线程的基础熟悉设置等参考sun公司 的《多线程编程指南》非常详细讲述了posix线程库。


By Water-              Aug,17th.2010


——————————————————————————————————


线程的调度策略分为3个:SCHED_OTHER,SCHED_FIFO,SCHED_RR。


SCHED_OTHER是非实时分时调度策略,线程优先级为0;


试验结果(linux2.6 Montavista 5.0):每个线程都不能强占其它线程,但是线程都受到时间片的限制,并不是线程不主动退出(包括被阻塞),就会一直占用。


但是在sun公司的 《多线程编程手册》中,其说这种情况 线程会一直占用。


SCHED_FIFO是实时先进先出调度策略,即一当占用CPU,除非自己阻塞或结束或有更高优先级线程,否则会一直运行,线程优先级为1-99;


线程会按不同的优先级来分为不同的队列,同优先级的线程是按FIFO来调度的。


SCHED_RR是实时分时调度策略,其不会一直占用CPU,运行一个时间片后会让出CPU给自己同优先级的线程;其实SCHED_RR与SCHED_FIFO基本是相似的,只是前者会受到时间片的限制,相同优先级的线程,用时间片来调度。而FIFO的话,正在运行的线程,是不会被其他同优先级线程强占的,除非自己主动退出或被阻塞。所以在采用FIFO策略时,千万别使用一直占用的线程(不主动退出,也没有挂起的条件),否则其他同优先级线程永远不会运行了。这种情况最好使用RR策略。


 


指出:SCHED_OTHER是不支持优先级使用的,而SCHED_FIFO和SCHED_RR支持优先级的使用,他们分别为1和99,数值越大优先级越高。实时调度策略会抢占非实时调度策略,即只要有SCHED_FIFO或SCHED_RR这两个实时调度策略的线程,像SCHED_OTHER的非实时调度策略的线程就不会得到运行,除非所有的实时调度策略的线程阻塞或结束。


 


下面测试程序thread_attr_test.c来测试线程的缺省属性;


 


//thread_attr_test.c


#include


#include


#include


#include


#include


 


void * thrd_fun( void * arg)


{


      int my_policy;


      struct sched_param my_param;


      int status;


      pid_t pid;


       pid = getpid();


       printf("my pid is %d \n",pid);


      status = pthread_getschedparam ( pthread_self (), &my_policy, &my_param );


 


     printf ("thread_routine running   policy is %s,priority is %d \n", (my_policy == SCHED_FIFO ?"FIFO"


                : (my_policy == SCHED_RR ?"RR"


                : (my_policy ==        SCHED_OTHER ? "OTHER"


                : "       UNKOWN" ))),


          my_param.sched_priority);


}


 


 


int main (int argc, char *argv[])


{


     pthread_t thread_id;


     pthread_attr_t thread_attr;


     int thread_policy;


     struct sched_param thread_param;


     int status ,rr_min_priority ,rr_max_priority;


       int inherit;


       int detachstate;


       int policy;


       int scope;


       struct sched_param param;


     pid_t pid;


       pid = getpid();


       printf("main pid is %d\n",pid);


      status = pthread_attr_init ( &thread_attr);


     status = pthread_attr_getschedpolicy ( &thread_attr , &thread_policy);


     status = pthread_attr_getschedparam ( &thread_attr, &thread_param);


     printf ("default policy is %s,priority is %d \n", (thread_policy == SCHED_FIFO ?"FIFO"


                : (thread_policy == SCHED_RR ?"RR"


                : (thread_policy ==   SCHED_OTHER ? "OTHER"


                : "       UNKOWN" ))),


          thread_param.sched_priority);


 


 


    


       pthread_attr_getinheritsched(&thread_attr,&inherit);


       if(inherit==PTHREAD_EXPLICIT_SCHED)


              printf("PTHREAD_EXPLICIT_SCHED\n");


       if(inherit==PTHREAD_INHERIT_SCHED)


              printf("PTHREAD_INHERIT_SCHED\n");


 


      


       pthread_attr_getdetachstate(&thread_attr,&detachstate);


       if(detachstate==PTHREAD_CREATE_DETACHED)


              printf("PTHREAD_CREATE_DETACHED\n");


       if(detachstate==PTHREAD_CREATE_JOINABLE)


              printf("PTHREAD_CREATE_JOINABLE\n");//非分离


      


       pthread_attr_getschedpolicy(&thread_attr,&policy);


       if(policy==SCHED_OTHER)


              printf("SCHED_OTHER\n");


       if(policy==SCHED_FIFO)


              printf("SCHED_FIFO\n");


       if(policy==SCHED_RR)


              printf("SCHED_RR\n");


 


      


       pthread_attr_getscope(&thread_attr,&scope);


       if(scope==PTHREAD_SCOPE_SYSTEM)


              printf("PTHREAD_SCOPE_SYSTEM\n");


       if(scope==PTHREAD_SCOPE_PROCESS)


              printf("PTHREAD_SCOPE_PROCESS\n");


 


      


       pthread_attr_getschedparam(&thread_attr,¶m);


       printf("priority:%d\n",param.sched_priority);


 


 


#if defined (_POSIX_THREAD_PRIORIY_SCHEDULING )


   printf("supports");


#else


  printf("not supports\n");


#endif


       //struct sched_param param;


       param.sched_priority=1;


 


       pthread_attr_setschedpolicy(&thread_attr,SCHED_FIFO);


       pthread_attr_setschedparam(&thread_attr,¶m);//设置成实时策略后必须设定优先级,否则线程将创建失败


       pthread_attr_setinheritsched(&thread_attr,PTHREAD_EXPLICIT_SCHED); //必须把继承属性修改为PTHREAD_EXPLICIT_SCHED才能有效


                                                                      //否则将继续继承父进程的策略


       status = pthread_create( &thread_id ,&thread_attr, thrd_fun , NULL);


       if (status != 0)


       {


              printf("can't creat!\n");


             exit (1);  


       }


      status = pthread_join (thread_id ,NULL);


      return 0;


}


 


 


 


 


 


运行的结果为(FC12-2.6.31.5内核):


main pid is 4318


default policy is OTHER,priority is 0


PTHREAD_INHERIT_SCHED


PTHREAD_CREATE_JOINABLE


SCHED_OTHER


PTHREAD_SCOPE_SYSTEM


priority:0


not supports


my pid is 4318


thread_routine running   policy is FIFO,priority is 1


 


 


运行的结果为(在arm开发板上2.4.18的内核):


main pid is 111


default policy is OTHER,priority is 0


PTHREAD_EXPLICIT_SCHED 这里和2.6的内核属性不同??


PTHREAD_CREATE_JOINABLE


SCHED_OTHER


PTHREAD_SCOPE_SYSTEM


priority:0


not supports


my pid is 113


thread_routine running   policy is FIFO,priority is 1


从结果我们可以得出其缺省属性为:


OTHER非实时调度策略,且优先级为0(无优先级高低之分);


为继承属性(2.6)       非继承(2.4);


为非分离属性;


为绑定属性,即与系统中所有线程(包括其他进程的线程)竞争。


经过pthread_attr_setschedpolicy 设置后把子线程的调度策略设置成了FIFO,且优先级为1;所设定的优先级范围必须在最大和最小值之间。可以通过sched_get_priority_max和sched_get_priority_min来获取。这程序中只是简单的测试。


需要注意的是:


如果修改了调度策略为实时的(即FIFO或RR),则必须为其设置优先级,否则线程将创建失败;记住要把继承属性修改为PTHREAD_EXPLICIT_SHED,否则子线程将继续继承父线程的相关策略,使得策略设置无效。


存在的问题:


有些系统需要定义_POSIX_THREAD_PRIORITY_SCHEDULING 才能设置线程的调度策略。但本次试验中测试出系统没有定义有些系统需要定义_POSIX_THREAD_PRIORITY_SCHEDULING 但仍然可以设置线程的调度策略,有点不明白。


 


调度策略的验证:


下面对SCHED_FIFO是实时先进先出调度策略,即一当占用CPU,除非自己阻塞或结束或有更高优先级线程,否则会一直运行;这个策略进行验证。


 


 


测试程序thread_shed_test.c如下:


 


 


#include


#include


#define    FIFO_TEST  


void *FunThread1(void *arg)


{


       int i,j;


       int policy;


       struct sched_param param;


       pthread_getschedparam(pthread_self(),&policy,¶m);


       if(policy==SCHED_OTHER)


              printf("SCHED_OTHER\n");


       if(policy==SCHED_RR)


              printf("SCHED_RR\n");


       if(policy==SCHED_FIFO)


              printf("SCHED_FIFO\n");


       for(i=1;i <500;i++)


       {


              for(j=1;j <50000;j++)


              {


              }


              //while(1); //调用这个来测试 FIFO时候受时间片的限制


              printf("thread 1\n");


       }


       printf("Thread1 exit\n");


}


void* FunThread2(void *arg)


{


       int i;


       // for(i=1;i <5000;i++)


       sched_yield();


       sched_yield();


       printf("Thread2 exit\n");


}


void* FunThread3(void *arg)


{


       int i;


       // for(i=1;i <5000;i++)


       sched_yield();


       sched_yield();


       printf("Thread3 exit\n");


}


int main()


{


       int i;


       pthread_t ppid1,ppid2,ppid3;


       struct sched_param param;


       pthread_attr_t attr,attr2;


       i=getuid();


       if(i==0)


              printf("The current user is root\n");


       else


              printf("The current user is not root\n");


       param.sched_priority=1;


      


       pthread_attr_init(&attr);


       pthread_attr_init(&attr2);


       pthread_attr_setschedpolicy(&attr2,SCHED_FIFO);


       pthread_attr_setschedparam(&attr2,¶m);


       pthread_attr_setinheritsched(&attr2,PTHREAD_EXPLICIT_SCHED); //新加,指定不继承父线程调度策略


#ifdef      FIFO_TEST


       pthread_create(&ppid1,&attr2,FunThread1,NULL);


#else


       pthread_create(&ppid1,NULL,FunThread1,NULL);


#endif


 


       pthread_create(&ppid2,&attr,FunThread2,NULL);


       pthread_create(&ppid3,&attr,FunThread3,NULL);


       pthread_join(ppid1,NULL);


       pthread_join(ppid2,NULL);


       pthread_join(ppid3,NULL);


       pthread_attr_destroy(&attr);


       pthread_attr_destroy(&attr2);


       return 0;


}  


 


 


 


 


 


 


 


 


 


 


运行的结果为(FC12-2.6.31.5内核):


SCHED_FIFO


thread 1


thread 1


thread 1


.


.


.


.


Thread 1


thread 1


thread 1


Thread1 exit


Thread2 exit


Thread3 exit


在main函数里创建线程一时将其调度策略设置为SCHED_FIFO,优先级为1,线程二和线程三的调度策略为SCHED_OTHER,优先级为0,正确结果应该是线程一先运行结束才会轮到线程二和线程三。从运行结果来看似乎正确,但请看后文;


若改为用OTHER方式(注释掉‘#define FIFO_TEST’       )则结果为:


SCHED_OTHER


thread 1


thread 1


thread 1


.


.


.


.


Thread 1


Thread2 exit


thread 1


thread 1


.


.


.


.


thread 1


thread 1


Thread3 exit


thread 1


thread 1


.


.


.


.


thread 1


thread 1


 


Thread1 exit


这种情况下,是时分调度的,3个线程都有时间片限制,时间片到则被其它线程代替。结果验证时正确的。


 


但是是否线程1(FIFO策略)的只要自己不退让或阻塞就不会被线程2或3 强占了??


 


在FunThread1()中加入while(1)死循环后再来测试


运行结果为:(FC12-2.6.31.5内核):


The current user is root


SCHED_FIFO


Thread2 exit


Thread3 exit


--


发现FIFO的线程1,在运行一段时间后线程2和3还是得以执行了。这证明在该系统上即使是FIFO的线程,其也受到了一个时间片的限制,在系统规定的时间片到时,其必须让出给其它线程执行。否则pc上的FC12这个系统将不能做其它的事情了(显然不可以)。但是这时候也可以明显的发现,此时PC机上的FC12系统对其它的操作响应(如鼠标等)已经很慢了。这证明这个所谓的时间片应该比较长。


 


但是把这个程序在arm开发板上运行:


运行的结果为(在arm开发板上2.4.18的内核):


The current user is root


SCHED_FIFO


------


结果显示与FIFO的理论完全相符合,即即一当占用CPU,除非自己阻塞或结束或有更高优先级线程,否则会一直运行。


 


两种平台上的不同的原因猜想:


可能在PC机上的FC12加入了时间片的限制,来时这个系统不容易崩溃。而ARM开发板上的linux则没有做相关处理。


你可能感兴趣的:(关于linux调度策略的学习总结)