policy:调度策略
0:SCHED_OTHER,其他普通的调度(分时调度),仅能设置优先级0或 >99,调度器总会给此类线程分配一定的CPU资源,只不过是被分配到的频次和时间片长度问题。
优缺点:
适用场景:实时性要求不高,但要求必须能被执行的线程。
1:SCHED_FIFO,(FIFO先进先出)抢占式调度,设置优先级1-99,同一优先级的多个线程(包括抢占式、轮轮转式)中,一旦某个抢占式线程获取CPU,除非被更高优先级线程抢占(比如在非实时线程中创建一个更高优先级的实时线程),或该线程主动让出CPU资源,否则该线程将会一直占用CPU(但总会分配一点资源给SCHED_OTHER非实时线程)。
优缺点:FIFO调度本身实现了数据的互斥, 在线程运行的时间内其他相同优先级线程无法进行资源抢占。但可能某个线程长时间占用CPU,导致其它线程获取不到CPU。
适用场景:实时性要求高,不希望被频繁打断的任务。
2:SCHED_RR,时间片轮转(RR: RoundRobin)调度,设置优先级1-99。时间片是线程运行的最小时间单元,由操作系统预先设定。当时间片用完时,该线程自动让出CPU, 之后内核会按照和FIFO相同的方式搜索下一个工作线程
适用场景:实时性要求高,允许被频繁打断的任务。
优缺点:轮转调度可以防止某一个任务连续占用太多的资源,而导致其他线程信息得不到及时处理。缺点是轮转调度会增大由于任务切换而导致的开销
总结:
应用程序中不管存在以上一种或三种线程类型,
程序中存在三种类型的线程时,对于非实时线程, 每隔一段时间(由系统分配,大概几秒钟)总会被分配一点CPU资源;
程序中存在三种类型的线程时,对于实时线程,当每次线程切换时,总是先执行就绪态线程队列中 最高优先级的线程。
Linux SCHED_FIFO, SCHED_RR和SCHED_OTHER-CSDN博客
#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;
}