Linux线程调度

线程调度

在 Linux 中,调度器是基于线程的调度策略(scheduling policy)和静态调度优先级(static scheduling priority)来决定哪个线程来运行。
对于以下三种调度策略:SCHED_OTHER, SCHED_IDLE, SCHED_BATCH,其调度优先级是不起作用的,即可以将调度优先级视为 0;调度策略 SCHED_FIFO 和 SCHED_RR 是实时策略,其调度值范围是 1 到 99,数值越大优先级越高。下面介绍几种常见的调度策略:

  • SCHED_OTHER:该策略是分时调度(time-sharing scheduling)策略,它是 Linux 线程默认的调度策略。SCHED_OTHER 策略的静态优先级总是为 0,对于该策略列表上的线程,调度器是基于动态优先级(dynamic priority)来调度的。动态优先级跟 nice 值相关,该值会随着线程的运行时间而动态改变,以确保所有具有 SCHED_OTHER 策略的线程公平运行。在 Linux 上,nice 值的范围是 -20 到 +19,默认值为0;nice值越大则优先级越低。
  • SCHED_FIFO:先入先出调度策略(First in-first out scheduling)。该策略就是一旦线程抢占到 cpu 则一直运行,直到被更高优先级的线程抢占或或自己主动放弃。
  • SCHED_RR:时间片轮转调度 (Round-robin scheduling)。该策略是 SCHED_FIFO 基础上改进来的,增加了一个时间片限制。当时间片用完后,系统将把该线程置于队列末尾。放在队列尾保证了所有具有相同优先级的 RR 任务的调度公平。

相关接口

int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destory(pthread_attr_t *attr);

线程属性对象的初始化和消耗。

int sched_get_priority_max(int policy); 
int sched_get_priority_min(int policy); 

获取指定调度策略可以设置的最大优先级和最小优先级。

int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); 

设置线程的调度策略。参数 policy 可以是 SCHED_FIFO, SCHED_RR 和 SCHED_OTHER。系统创建线程时,默认的线程调度策略是 SCHED_OTHER。

int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);

获取线程的调度策略。

struct sched_param {
int sched_priority; /* Scheduling priority */
};
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);

设置线程的调度优先级。

int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);

获取线程调度的优先级。

int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);

设置线程继承权。线程优先级不是随便就能设置的,需要放弃线程的继承权。第二个参数 inheritsched 有两个取值:PTHREAD_INHERIT_SCHED(拥有继承权)和 PTHREAD_EXPLICIT_SCHED(放弃继承权)。默认为 PTHREAD_INHERIT_SCHED。

int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask); 


int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,
const cpu_set_t *cpuset);
int pthread_attr_setaffinity_np(pthread_attr_t *attr,
size_t cpusetsize, const cpu_set_t *cpuset); 

以上两组接口都是设置线程的 CPU 亲和性。设置线程的亲和性可以使得线程绑定到一个或多个指定的 CPU 上运行。在多处理器系统上,设置 CPU 亲和性可以提高性能(主要原因是尽可能避免了cache 失效和切换到其他 CPU 的消耗)。

实例测试

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void show_thread_policy(int threadno)
{
    int policy;
    struct sched_param param;
    pthread_getschedparam(pthread_self(), &policy, &param);
    switch(policy) {
    case SCHED_OTHER:
        printf("SCHED_OTHER %d, priority = %d\n", threadno, param.sched_priority);
        break;
    case SCHED_RR:
        printf("SCHDE_RR %d, priority = %d\n", threadno, param.sched_priority);
        break;
    case SCHED_FIFO:
        printf("SCHED_FIFO %d, priority = %d\n", threadno, param.sched_priority);
        break;
    default:
        printf("UNKNOWN\n");
    }
}
void* run( void *arg )
{
    int i, j;
    long threadno = (long)arg;
    printf( "thread %d start\n", threadno);
    sleep(1);
    show_thread_policy(threadno);
    for(i = 0; i < 10; ++i) {
        for(j = 0; j < 100000000; ++j){}
        printf("thread %d\n", threadno);
    }
    printf("thread %d exit\n", threadno);
    return NULL;
}
int main(int argc, char *argv[])
{
    long i;
    pthread_attr_t attr[6];
    pthread_t pth[6];
    struct sched_param param;
    for(i = 0; i < 6; ++i) {
        pthread_attr_init(&attr[i]);
        if (i < 2) { 
            param.sched_priority = 40;                  
            pthread_attr_setschedpolicy(&attr[i], SCHED_FIFO);
            pthread_attr_setschedparam(&attr[i], &param);
            pthread_attr_setinheritsched(&attr[i], PTHREAD_EXPLICIT_SCHED);
        }
        if(i < 4 && i >= 2) {
            param.sched_priority = 80;                  
            pthread_attr_setschedpolicy(&attr[i], SCHED_FIFO);
            pthread_attr_setschedparam(&attr[i], &param);
            pthread_attr_setinheritsched(&attr[i], PTHREAD_EXPLICIT_SCHED);
        }
    }
    for(i = 0; i < 6; ++i) {
        if (i < 4) {
            pthread_create(&pth[i], &attr[i], run, (void*)i);
        } else {
            pthread_create(&pth[i], NULL, run, (void*)i);
        }
    }             
    for(i = 0; i < 6; ++i)                    
        pthread_join(pth[i], NULL);                    
    for(i = 0; i < 6; ++i)                    
        pthread_attr_destroy(&attr[i]);
    return 0;                           
}

运行结果:

thread 0 start
thread 1 start
thread 2 start
thread 3 start
thread 5 start
thread 4 start
SCHED_FIFO 0, priority = 40
SCHED_FIFO 1, priority = 40
SCHED_FIFO 2, priority = 80
SCHED_FIFO 3, priority = 80
SCHED_OTHER 4, priority = 0
SCHED_OTHER 5, priority = 0
thread 3
thread 0
thread 4
thread 2
thread 1
thread 5
thread 0
thread 4
thread 1
thread 3
thread 5
thread 2
thread 4
thread 1
thread 5
thread 0
thread 3
thread 2
thread 4
thread 1
thread 5
thread 3
thread 4
thread 2
thread 1
thread 5
thread 0
thread 3
thread 4
thread 2
thread 1
thread 5
thread 3
thread 1
thread 4
thread 2
thread 0
thread 3
thread 1
thread 2
thread 5
thread 3
thread 4
thread 1
thread 2
thread 0
thread 5
thread 3
thread 1
thread 1 exit
thread 2
thread 4
thread 0
thread 3
thread 3 exit
thread 5
thread 2
thread 2 exit
thread 4
thread 4 exit
thread 0
thread 5
thread 5 exit
thread 0
thread 0
thread 0 exit
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值