實時和非實時調度策略測試總結


創建兩個線程,用不同的實時調度(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的ubuntu系統的測試結果,在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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM