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, ¶m1);
if(errno != 0)
{
perror("setparam failed\n");
return -1;
}
errno = pthread_attr_setschedparam(&attr2, ¶m2);
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;
}