task_struct 结构体
task_struct 结构体定义了4个关于优先级(prio)的参数,这是由于Linux内核里不止一种调度器导致的。
参数 | 实时调度器进程 | CFS调度器进程 |
---|---|---|
prio | 正常情况下,prio等于normal_prio | 正常情况下,prio等于normal_prio |
normal_prio | 99-rt_priority | static_prio |
static_prio | 无意义 | 120+nice值 |
rt_priority | 1~99 | 无意义 |
prio 调度优先级
进程的动态优先级,是调度器使用的优先级
normal_prio 正常优先级
normal_prio值是根据调度器类型计算出来的
对于实时进程:normal_prio = 99 - rt_priority
对于非实时进程: normal_prio = static_prio
代码实现如下:
#define MAX_RT_PRIO 100
static inline int __normal_prio(struct task_struct *p)
{
return p->static_prio;
}
static inline int normal_prio(struct task_struct *p)
{
int prio;
if (task_has_dl_policy(p))
prio = MAX_DL_PRIO-1;
else if (task_has_rt_policy(p))
prio = MAX_RT_PRIO-1 - p->rt_priority;
else
prio = __normal_prio(p);
return prio;
}
static_prio 静态优先级
静态优先级,在进程启动时分配,在被CFS调度的进程中才有意义,用户可以通过修改nice值来修改静态优先级,内核不存储nice值,只会通过NICE_TO_PRIO宏将nice值转换为static_prio。
#define DEFAULT_PRIO 120
#define NICE_TO_PRIO(nice) ((nice) + DEFAULT_PRIO)
rt_priority 实时优先级
实时优先级,在被实时调度器调度的进程中才会有意义
应用编程修改调度策略
SCHED_NORMAL( 老版本也称SCHED_OTHER): CFS调度:分时调度 不支持优先级
SCHED_FIFO: 实时调度策略 先入先调度 优先级 1~99
SCHED_RR: 实时调度策略 时间片轮转 优先级 1~99
SCHED_NORMAL CFS调度策略
采用SCHED_NORMAL调度策略调度的进程是交给内核的CFS完全公平调度器调度的,对于应用程序开发者来说,被CFS调度器调度的进程是没有优先级之说的,只能靠修改nice值改变权重来增加或减少被调度的时间。
对于SCHED_NORMAL调度策略的进程,调度器采用其静态优先级作为调度依据,进程在创建时,nice值默认为0,也就是说用户创建一个SCHED_NORMAL调度策略的进程,其调度的动态优先级prio值为120,其值高于实时优先级0~100的范围,所以只要就绪队列里存在一个实时调度进程,都会将其抢占。
SCHED_FIFO 和 SCHED_RR 实时调度策略
采用SCHED_FIFO 和 SCHED_RR调度策略的进程是交给实时调度器调度的,应用开发者是可以调整其优先级的,范围为1~99,值越大,表示优先级越高。
但是对于内核调度区来说,进程的优先级是数值越低优先级越高,这就是在上一章节所讲的,此时动态优先级prio = 99 - rt_priority,用户不能直接修改prio参数,只能设置的优先级是rt_priority参数。
相关的系统调用
获取优先级范围
sched_get_priority_min(int policy) 获取优先级最小值
sched_get_priority_max(int policy) 获取优先级最大值
policy传参
获取优先级最大值和最小值后,在设置线程的优先级时,我们就不会设置超出范围的优先级值。
直接写代码验证一下
#include<stdio.h>
#include <pthread.h>
#include <sched.h>
#include <assert.h>
static void show_thread_priority(int policy)
{
int prioritymin = sched_get_priority_min(policy);
int prioritymax = sched_get_priority_max(policy);
assert(prioritymin != -1);
assert(prioritymax != -1);
printf("priority %d ~ %d\n",prioritymin,prioritymax);
}
int main(int argc,char* argv[])
{
printf("------- SCHED_FIFO priority-------\n");
show_thread_priority(SCHED_FIFO);
printf("------- SCHED_RR priority-------\n");
show_thread_priority(SCHED_RR);
printf("------- SCHED_OTHER priority-------\n");
show_thread_priority(SCHED_OTHER);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sDgytHEH-1632535885317)(en-resource://database/16884:1)]
从以上代码的运行结果,可以看出SCHED_FIFO和SCHED_RR调度策略可以使用的优先级范围为199,而SCHED_OTHER调度策略的优先级范围为00,也就是不支持优先级使用。
修改线程的调度策略
int pthread_attr_setschedpolicy(pthread_attr_t *attr,int policy)
int pthread_attr_getschedpolicy(pthread_attr_t attr,int policy)
#include<stdio.h>
#include <pthread.h>
#include <sched.h>
#include <assert.h>
//获取线程的调度策略
static int get_thread_policy(pthread_attr_t *attr)
{
int plicy;
int rs=pthread_attr_getschedpolicy(attr,&plicy);
assert(rs==0);
switch(plicy)
{
case SCHED_FIFO:
printf("policy=SCHED_FIFO.\n");
break;
case SCHED_RR:
printf("policy=SCHED_RR.\n");
break;
case SCHED_OTHER:
printf("policy=SCHED_OTHER.\n");
break;
default:
printf("policy=UNKNOWN.\n");
break;
}
return plicy;
}
//改变线程的调度策略
static void set_thread_policy(pthread_attr_t *attr,int policy)
{
int ret = pthread_attr_setschedpolicy(attr,policy);
assert(ret == 0);
}
int main(int argc,char* argv[])
{
pthread_attr_t attr;
int rs=pthread_attr_init(&attr);
assert(0==rs);
printf("------- Set Policy to SCHED_FIFO -------\n");
set_thread_policy(&attr,SCHED_FIFO);
get_thread_policy(&attr);
printf("------- Set Policy to SCHED_RR -------\n");
set_thread_policy(&attr,SCHED_RR);
get_thread_policy(&attr);
printf("------- Set Policy to SCHED_OTHER -------\n");
set_thread_policy(&attr,SCHED_OTHER);
get_thread_policy(&attr);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IAFL0u77-1632535886012)(en-resource://database/16886:1)]