1. linux优先级的表示
1.1 优先级的内核表示
linux优先级概述
在用户空间通过nice命令设置进程的静态优先级, 这在内部会调用nice系统调用, 进程的nice值在-20~+19之间. 值越低优先级越高.
setpriority系统调用也可以用来设置进程的优先级. 它不仅能够修改单个线程的优先级, 还能修改进程组中所有进程的优先级, 或者通过制定UID来修改特定用户的所有进程的优先级
内核使用一些简单的数值范围0~139表示内部优先级, 数值越低, 优先级越高。
从0~99的范围专供实时进程使用, nice的值[-20,19]则映射到范围100~139
linux2.6内核将任务优先级进行了一个划分, 实时优先级范围是0到MAX_RT_PRIO-1(即99),而普通进程的静态优先级范围是从MAX_RT_PRIO到MAX_PRIO-1(即100到139).
优先级范围 | 描述 |
---|---|
0——99 | 实时进程 |
100——139 | 非实时进程 |
内核的优先级表示
内核表示优先级的所有信息基本都放在include/linux/sched/prio.h中, 其中定义了一些表示优先级的宏和函数.
优先级数值通过宏来定义, 如下所示,
其中MAX_NICE和MIN_NICE定义了nice的最大最小值
而MAX_RT_PRIO指定了实时进程的最大优先级,而MAX_PRIO则是普通进程的最大优先级数值
/* http://lxr.free-electrons.com/source/include/linux/sched/prio.h?v=4.6#L4 */
#define MAX_NICE 19
#define MIN_NICE -20
#define NICE_WIDTH (MAX_NICE - MIN_NICE + 1)
/* http://lxr.free-electrons.com/source/include/linux/sched/prio.h?v=4.6#L24 */
#define MAX_PRIO (MAX_RT_PRIO + 40)
#define DEFAULT_PRIO (MAX_RT_PRIO + 20)
宏 | 值 | 描述 |
---|---|---|
MIN_NICE | -20 | 对应于优先级100, 可以使用NICE_TO_PRIO和PRIO_TO_NICE转换 |
NICE_WIDTH | 40 | nice值得范围宽度, 即[-20, 19]共40个数字的宽度 |
MAX_RT_PRIO, MAX_USER_RT_PRIO | 10 0 |
实时进程的最大优先级 |
MAX_PRIO | 14 0 |
普通进程的最大优先级 |
DEFAULT_PRIO | 12 0 |
进程的默认优先级, 对应于nice=0 |
MAX_DL_PRIO | 0 | 使用EDF最早截止时间优先调度算法的实时进程最大的优先级 |
而内核提供了一组宏将优先级在各种不同的表示形之间转移
// http://lxr.free-electrons.com/source/include/linux/sched/prio.h?v=4.6#L27
/*
* Convert user-nice values [ -20 ... 0 ... 19 ]
* to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
* and back.
*/
#define NICE_TO_PRIO(nice) ((nice) + DEFAULT_PRIO)
#define PRIO_TO_NICE(prio) ((prio) - DEFAULT_PRIO)
/*
* 'User priority' is the nice value converted to something we
* can work with better when scaling various scheduler parameters,
* it's a [ 0 ... 39 ] range.
*/
#define USER_PRIO(p) ((p)-MAX_RT_PRIO)
#define TASK_USER_PRIO(p) USER_PRIO((p)->static_prio)
#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO))
还有一些nice值和rlimit值之间相互转换的函数nice_to_rlimit和rlimit_to_nice, 这在nice系统调用进行检查的时候很有用, 他们定义在include/linux/sched/prio.h, L47中, 如下所示
/*
* Convert nice value [19,-20] to rlimit style value [1,40].
*/
static inline long nice_to_rlimit(long nice)
{
return (MAX_NICE - nice + 1);
}
/*
* Convert rlimit style value [1,40] to nice value [-20, 19].
*/
static inline long rlimit_to_nice(long prio)
{
return (MAX_NICE - prio + 1);
}
DEF最早截至时间优先实时调度算法的优先级描述
此外新版本的内核还引入了EDF实时调度算法, 它的优先级比RT进程和NORMAL/BATCH进程的优先级都要高, 关于EDF的优先级的设置信息都早内核头文件include/linux/sched/deadline.h
因此内核将MAX_DL_PRIO设置为0, 可以参见内核文件include/linux/sched/deadline.h
#define MAX_DL_PRIO 0
此外也提供了一些EDF优先级处理所需的函数, 如下所示, 可以参见内核文件include/linux/sched/deadline.h
static inline int dl_prio(int prio)
{
if (unlikely(prio < MAX_DL_PRIO))
return 1;
return 0;
}
static inline int dl_task(struct task_struct *p)
{
return dl_prio(p->prio);
}
static inline bool dl_time_before(u64 a, u64 b)
{
return (s64)(a - b) < 0;
}
1.2 进程的优先级表示
struct task_struct
{
/* 进程优先级
* prio: 动态优先级,范围为100~139,与静态优先级和补偿(bonus)有关
* static_prio: 静态优先级,static_prio = 100 + nice + 20 (nice值为-20~19,所以static_prio值为100~139)
* normal_prio: 没有受优先级继承影响的常规优先级,具体见normal_prio函数,跟属于什么类型的进程有关
*/
int prio, static_prio, normal_prio;
/* 实时进程优先级 */
unsigned int rt_priority;
}
动态优先级 静态优先级 实时优先级
其中task_struct采用了三个成员表示进程的优先级:prio和normal_prio表示动态优先级, static_