Linux线程调度策略与优先级

policy:调度策略

0:SCHED_OTHER,其他普通的调度(非实时线程),仅能设置优先级0,调度器总会给此类线程分配一定的CPU资源,只不过是被分配到的频次和时间片长度问题。

适用场景:实时性要求不高,但要求必须能被执行的线程。
1:SCHED_FIFO,抢占式调度(实时线程),设置优先级1-99,同一优先级的多个线程(包括抢占试、轮询试)中,一旦某个抢占试线程获取CPU,除非被更高优先级线程抢占(比如在非实时线程中创建一个更高优先级的实时线程),或该线程主动让出CPU资源,否则该线程将会一直占用CPU(但总会分配一点资源给SCHED_OTHER非实时线程)。

适用场景:实时性要求高,不希望被频繁打断的任务。
2:SCHED_RR,轮询式调度(实时线程),设置优先级1-99,同一优先级的多个线程(轮询试),没给线程被分配相同时间片的CPU资源。

适用场景:实时性要求高,允许被频繁打断的任务。

总结:
应用程序中不管存在以上一种或三种线程类型,
对于非实时线程, 每隔一段时间(由系统分配,大概几秒钟)总会被分配一点CPU资源;
对于实时线程,当每次线程切换时,总是先执行就绪态线程队列中 最高优先级的线程。

#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sched.h>


void *start_routine(void *arg)
{
    int i, j;

    while(1)
    {
        fprintf(stderr, "%c ", *(char *)arg);
        for(i=0; i<100000; i++)
            for(j=0; j<1000; j++);
    }

    pthread_exit(NULL);
}


int main(void)
{

    pthread_t tid1, tid2, tid3;
    pthread_attr_t attr1, attr2;
    struct sched_param param1, param2;

    /* 线程属性变量的初始化 */
    pthread_attr_init(&attr1);
    pthread_attr_init(&attr2);


    /* 设置线程是否继承创建者的调度策略 PTHREAD_EXPLICIT_SCHED:不继承才能设置线程的调度策略*/
    errno = pthread_attr_setinheritsched(&attr1, PTHREAD_EXPLICIT_SCHED);
    if(errno != 0)
    {
        perror("setinherit failed\n");
        return -1;
    }

    /* 设置线程是否继承创建者的调度策略 PTHREAD_EXPLICIT_SCHED:不继承才能设置线程的调度策略*/
    errno = pthread_attr_setinheritsched(&attr2, PTHREAD_EXPLICIT_SCHED);
    if(errno != 0)
    {
        perror("setinherit failed\n");
        return -1;
    }

    /* 设置线程的调度策略:SCHED_FIFO:抢占性调度; SCHED_RR:轮寻式调度;SCHED_OTHER:非实时线程调度策略*/
    errno = pthread_attr_setschedpolicy(&attr1, SCHED_RR);
    if(errno != 0)
    {
        perror("setpolicy failed\n");
        return -1;
    }

    errno = pthread_attr_setschedpolicy(&attr2, SCHED_RR);
    if(errno != 0)
    {
        perror("setpolicy failed\n");
        return -1;
    }

    //设置优先级的级别
    param1.sched_priority = 1;
    param2.sched_priority = 1;

    //查看抢占性调度策略的最小跟最大静态优先级的值是多少
    printf("min=%d, max=%d\n", sched_get_priority_min(SCHED_FIFO), sched_get_priority_max(SCHED_FIFO));


    /* 设置线程静态优先级 */
    errno = pthread_attr_setschedparam(&attr1, &param1);
    if(errno != 0)
    {
        perror("setparam failed\n");
        return -1;
    }

    errno = pthread_attr_setschedparam(&attr2, &param2);
    if(errno != 0)
    {
        perror("setparam failed\n");
        return -1;
    }

/* 创建三个测试线程 */
    /* 线程1,优先级1 */
    errno = pthread_create(&tid1, &attr1, start_routine, (void *)"1");
    if(errno != 0)
    {
        perror("create thread 1 failed\n");
        return -1;
    }
    /* 线程2,优先级1 */
    errno = pthread_create(&tid2, &attr2, start_routine, (void *)"2");
    if(errno != 0)
    {
        perror("create thread 2 failed\n");
        return -1;
    }
    /* 线程3,非实时线程,静态优先级0 */
    errno = pthread_create(&tid3, NULL, start_routine, (void *)"3");
    if(errno != 0)
    {
        perror("create thread 3 failed\n");
        return -1;
    }

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    pthread_join(tid3, NULL);

    pthread_attr_destroy(&attr1);
    pthread_attr_destroy(&attr2);

    return 0;
}