關於linux調度策略的學習總結

來源:互聯網
上載者:User

關於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 <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <unistd.h>

#include <sched.h>

 

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,&param);

       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,&param);//設定成即時策略後必須設定優先順序,否則線程將建立失敗

       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 <stdio.h>

#include <pthread.h>

#define    FIFO_TEST  

void *FunThread1(void *arg)

{

       int i,j;

       int policy;

       struct sched_param param;

       pthread_getschedparam(pthread_self(),&policy,&param);

       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,&param);

       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則沒有做相關處理。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.