1. 程式人生 > 實用技巧 >實時和非實時排程策略測試總結

實時和非實時排程策略測試總結

建立兩個執行緒,用不同的實時排程(SCHED_FIFO,SCHED_RR)和非實時排程(SCHED_OTHER)策略,總結如下:

  • 用root身份執行,才能設定實時排程策略。否則,
    • 建立預設執行緒後,呼叫pthread_setschedparam()設定實時呼叫策略失敗。
    • 建立帶實時排程策略的attr引數的執行緒無法執行。
  • 同為實時排程執行緒,不論是SCHED_RR還是SCHED_FIFO,高優先順序執行緒都能對低優先順序執行緒實施搶佔,且在主動放棄CPU之前不會釋放佔用。
  • 相同優先順序的實時排程執行緒,
    • 如果同為SCHED_RR執行緒,執行緒之間分享時間片,輪轉執行。
    • 如果同為SCHED_FIFO執行緒,其中之一(誰先執行)會一直執行直到到其主動釋放佔用CPU,另一個才會執行。即同優先順序不會分享時間片。
    • 如果兩個分別為SCHED_RR,SCHED_FIFO執行緒,SCHED_RR執行緒會分享時間片,即時間片用完後會放棄佔用CPU,被SCHED_FIFO執行緒佔用。但SCHED_FIFO執行緒佔用後不會和SCHED_RR執行緒分享時間片,會一直執行到其主動釋放佔用後,SCHED_RR執行緒才會再次執行。
  • 兩個執行緒一個為實時呼叫執行緒,一個為非實時呼叫執行緒,實時執行緒不論是何優先順序(>0),何種排程方式,都能對非實時執行緒實施搶佔,且不會對非實時執行緒共享時間片。
  • 同為非實時排程執行緒,setpriority()(root才能設定)設定其nice值(-20~19,越小優先順序越高),影響排程器分配的時間片
    nice為19時,當有其他更高優先順序nice的執行緒在執行時,系統給nice19的執行緒分配的時間片相當少,甚至沒有。
  • 實時執行緒並且優先順序為最高99時,系統會顯示(top,ps命令等)該執行緒為rt。
  • 繫結CPU對執行緒效率(不論是實時還是非實時排程執行緒)有提高,因為執行緒在不同核心上切換有消耗。

#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define
__USE_GNU #include <pthread.h> #include <sched.h> long long a = 0; long long b = 0; int attach_cpu(int cpu_index) { int cpu_num = sysconf(_SC_NPROCESSORS_CONF); if (cpu_index < 0 || cpu_index >= cpu_num) { printf("cpu index ERROR!\n"); return -1; } cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(cpu_index, &mask); if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) { printf("set affinity np ERROR!\n"); return -1; } return 0; } void *thread1(void *param) { printf("t1 tid %d\n", gettid()); /*if (setpriority(PRIO_PROCESS, 0, 19) != 0) { printf("setpriority failed!\n"); }*/ attach_cpu(0); long long i; for (i = 0; i < 10000000000; i++) { a++; } } void *thread2(void *param) { printf("t2 tid %d\n", gettid()); if (setpriority(PRIO_PROCESS, 0, -20) != 0) { printf("setpriority failed!\n"); } attach_cpu(0); long long i; for (i = 0; i < 10000000000; i++) { b++; } } //#define C_SET int main() { pthread_t t1; pthread_t t2; #ifdef C_SET pthread_attr_t attr; #else int policy; #endif struct sched_param param; #ifdef C_SET if (pthread_attr_init(&attr) != 0) { printf("pthread_attr_init failed!\n"); return -1; } if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0) { printf("pthread_attr_setinheritsched failed!\n"); } if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) { printf("pthread_attr_setschedpolicy failed!\n"); } param.sched_priority = 10; if (pthread_attr_setschedparam(&attr, &param) != 0) { printf("pthread_attr_setschedparam failed!\n"); } if (pthread_create(&t1, &attr, thread1, NULL) != 0) #else if (pthread_create(&t1, NULL, thread1, NULL) != 0) #endif { printf("create t1 failed!\n"); return -1; } #ifndef C_SET param.sched_priority = 1; policy = SCHED_FIFO; if (pthread_setschedparam(t1, policy, &param) != 0) { printf("set t1 sched param failed!\n"); } #endif sleep(1); #ifdef C_SET param.sched_priority = 10; if (pthread_attr_setschedparam(&attr, &param) != 0) { printf("pthread_attr_setschedparam failed!\n"); } if (pthread_create(&t2, &attr, thread2, NULL) != 0) #else if (pthread_create(&t2, NULL, thread2, NULL) != 0) #endif { printf("create t2 failed!\n"); return -1; } #ifndef C_SET param.sched_priority = 99; policy = SCHED_FIFO; /* if (pthread_setschedparam(t2, policy, &param) != 0) { printf("set t2 sched param failed!\n"); }*/ #endif while (a != 10000000000 || b != 10000000000) { printf("a=%lld, b=%lld\n", a, b); sleep(1); } printf("a=%lld, b=%lld\n", a, b); pthread_join(t1, NULL); pthread_join(t2, NULL); return 0; }
測試程式碼

以上是在x86的unbuntu系統的測試結果,在Android上的測試結果類似,因為都是linux核心。在Android上沒有pthread_setaffinity_np(),需要用syscall系統呼叫。

syscall(__NR_sched_setaffinity, gettid(), sizeof(mask), &mask);

參考:

https://blog.csdn.net/maray/article/details/2900689

https://www.cnblogs.com/wanpengcoder/p/11767185.html

http://man7.org/linux/man-pages/man7/sched.7.html