1. 优先级的内核表示
用户空间可以通过nice命令设置进程的静态优先级;
进程的nice值在-20到+19之间;值越低表示优先级越高;
内核使用0~139来表示内部优先级;同样值越低优先级越高;
#define MAX_USER_RT_PRIO 100
#define MAX_RT_PRIO MAX_USER_RT_PRIO //最大实时优先级
#define MAX_PRIO (MAX_RT_PRIO + 40) //最大优先级
#define DEFAULT_PRIO (MAX_RT_PRIO + 20) //默认优先级
#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20) //nice值转优先级
#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20)
#define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio)
2. 计算优先级
动态优先级: task_struct->prio, 普通优先级:task_struct->normal_prio; 静态优先级:task_struct->static_prio;
static_prio是计算的起点,内核计算其他优先级,仅需p->prio=effective_prio(p);
static inline int rt_policy(int policy)
{
if (policy == SCHED_FIFO || policy == SCHED_RR)
return 1;
return 0;
}
static inline int task_has_rt_policy(struct task_struct *p)
{
return rt_policy(p->policy);
}
static inline int normal_prio(struct task_struct *p)
{
int prio;
if (task_has_rt_policy(p))
//由于更高的rt_priority值表示更高的实时优先级,而内核恰好相反表示;
prio = MAX_RT_PRIO-1 - p->rt_priority;
else
prio = __normal_prio(p);//return p->static_prio;
return prio;
}
static int effective_prio(struct task_struct *p)
{
p->normal_prio = normal_prio(p);
/*
如果是实时进程或已经提高到了实时优先级,则优先级保持不变,否则返回普通优先级;
*/
if (!rt_prio(p->prio))
return p->normal_prio;
return p->prio;
}
3. 计算负荷权重
进程的重要性不仅由优先级指定,还需要考虑task_struct->se.load;的负荷权重;
struct load_weight {
unsigned long weight; //权重值
unsigned long inv_weight;//用于计算负荷权重除的结果;
};
set_load_weight负责根据进程类型及静态优先级计算负荷权重;
static const int prio_to_weight[40] = {
/* -20 */ 88761, 71755, 56483, 46273, 36291,
/* -15 */ 29154, 23254, 18705, 14949, 11916,
/* -10 */ 9548, 7620, 6100, 4904, 3906,
/* -5 */ 3121, 2501, 1991, 1586, 1277,
/* 0 */ 1024, 820, 655, 526, 423,
/* 5 */ 335, 272, 215, 172, 137,
/* 10 */ 110, 87, 70, 56, 45,
/* 15 */ 36, 29, 23, 18, 15,
};
/*
* Inverse (2^32/x) values of the prio_to_weight[] array, precalculated.
*
* In cases where the weight does not change often, we can use the
* precalculated inverse to speed up arithmetics by turning divisions
* into multiplications:
*/
static const u32 prio_to_wmult[40] = {
/* -20 */ 48388, 59856, 76040, 92818, 118348,
/* -15 */ 147320, 184698, 229616, 287308, 360437,
/* -10 */ 449829, 563644, 704093, 875809, 1099582,
/* -5 */ 1376151, 1717300, 2157191, 2708050, 3363326,
/* 0 */ 4194304, 5237765, 6557202, 8165337, 10153587,
/* 5 */ 12820798, 15790321, 19976592, 24970740, 31350126,
/* 10 */ 39045157, 49367440, 61356676, 76695844, 95443717,
/* 15 */ 119304647, 148102320, 186737708, 238609294, 286331153,
};
static void set_load_weight(struct task_struct *p)
{
int prio = p->static_prio - MAX_RT_PRIO;
struct load_weight *load = &p->se.load; //获取权重
/*
* 若是空闲态,加载权重为最小值
*/
if (p->policy == SCHED_IDLE) {
load->weight = scale_load(WEIGHT_IDLEPRIO);
load->inv_weight = WMULT_IDLEPRIO;
return;
}
//利用转换表将优先级转为权重;
load->weight = scale_load(prio_to_weight[prio]);
load->inv_weight = prio_to_wmult[prio];
}
每降低一个nice值,则多获取10%的cpu时间,每升高一个nice值,则放弃10%的cpu时间;故将优先级转换为权重值;转换表见prio_to_weight;