可以通过chrt查看进程的调度策略和优先级
pencil: $ chrt -p 551 pid 551's current scheduling policy: SCHED_BATCH pid 551's current scheduling priority: 0 #实时优先级,普通进程为0 pencil: $ chrt -p 511 pid 511's current scheduling policy: SCHED_FIFO pid 511's current scheduling priority: 15 #实时进程优先级 1(优先级最低)~99(优先级最高)内核使用0~139表示内部优先级, task_struct.prio的数值越低, 优先级越高(注意:这里指的是 task_struct.prio,还有其他优先级表示,注意区分)
实时优先级范围是 0 - MAX_RT_PRIO-1(即0 ~ 99)
普通进程的静态优先级范围是从 MAX_RT_PRIO - MAX_PRIO-1(即100~139),nice的值[-20,19]的映射的范围就是对应优先级的100 - 139,
优先级范围描述0——99实时进程100——139非实时进程贴下这部分的代码,内核里面有详尽的注释
https://elixir.bootlin.com/linux/v5.1.5/source/include/linux/sched/prio.h #define MAX_NICE 19 #define MIN_NICE -20 #define NICE_WIDTH (MAX_NICE - MIN_NICE + 1) /* * Priority of a process goes from 0..MAX_PRIO-1, valid RT * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority * values are inverted: lower p->prio value means higher priority. * 这部分能看到SCHED_NORMAL/SCHED_BATCH的优先级在MAX_RT_PRIO..MAX_PRIO-1(100 ~ 139), * 即普通非实时进程。而p->prio越小优先级越高 * The MAX_USER_RT_PRIO value allows the actual maximum * RT priority to be separate from the value exported to * user-space. This allows kernel threads to set their * priority to a value higher than any user task. Note: * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO. */ #define MAX_USER_RT_PRIO 100 #define MAX_RT_PRIO MAX_USER_RT_PRIO #define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH) #define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2) /* * Convert user-nice values [ -20 ... 0 ... 19 ] * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ], * and back. 看到NICE值对应的是MAX_RT_PRIO..MAX_PRIO-1 [ -20 ... 0 ... 19 ] ~ [ MAX_RT_PRIO..MAX_PRIO-1 ] */ #define NICE_TO_PRIO(nice) ((nice) + DEFAULT_PRIO) #define PRIO_TO_NICE(prio) ((prio) - DEFAULT_PRIO)在内核task_struct中有四个字段表示优先级,分别是:static_prio,rt_priority,normal_prio,prio,这四种优先级需要注意 rt_priority 不是越小优先级越高,而是越大优先级越高,见下文
静态优先级实时优先级普通优先级动态优先级static_priort_prioritynormal_prioprio https://elixir.bootlin.com/linux/v5.1.5/source/include/linux/sched.h#L585 struct task_struct { ............ int recent_used_cpu; int wake_cpu; #endif int on_rq; /* prio: 动态优先级, 范围为100~139,与静态优先级和补偿(bonus)有关*/ int prio; /* static_prio: 静态优先级 * static_prio = NICE_TO_PRIO(nice) = (nice) + DEFAULT_PRIO = (nice) + (MAX_RT_PRIO + NICE_WIDTH / 2) * 即:static_prio = 100 + nice + 20 * nice值为-20~19,所以static_prio值为100~139 */ int static_prio; /* normal_prio: 动态优先级 */ int normal_prio; /* 实时进程优先级 1 ~ 99*/ unsigned int rt_priority; const struct sched_class *sched_class; ............prio
动态优先级
(1)值越小,进程优先级越高
(2)prio值为 -1 ~139
(3)调度器调度采用该优先级调度。该优先级会根据是否为实时进程采用下面的三个优先级来计算
static_prio
静态优先级
(1)值越小,进程优先级越高
(2)static_prio值为100~139,static_prio = nice + MAX_RT_PRIO + NICE_WIDTH / 2
(3)缺省值是 120
(4)用户空间可以通过nice()或者setpriority对该值进行修改。通过getpriority可以获取该值。
(5)新创建的进程会继承父进程的static priority。
normal_prio
动态优先级,
(1)值越小,进程优先级越高
(2)normal_prio值为 -1 ~139
(3)表示基于进程的静态优先级static_prio和调度策略计算出的优先级。普通进程static_prio = normal_prio
(4)进程fork时, 子进程会继承父进程的普通优先级
下面代码即为normal_prio计算方式
https://elixir.bootlin.com/linux/v5.1.5/source/kernel/sched/core.c#L820 /* * __normal_prio - return the priority that is based on the static prio */ static inline int __normal_prio(struct task_struct *p) { return p->static_prio; } /* * Calculate the expected normal priority: i.e. priority * without taking RT-inheritance into account. Might be * boosted by interactivity modifiers. Changes upon fork, * setprio syscalls, and whenever the interactivity * estimator recalculates. */ 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; }rt_priority
实时优先级
(1)用于表示实时进程优先级
(2)值越大,进程优先级越高
(3)rt_priority值为 0~99,0是普通进程,1~99是实时进程,99的优先级最高
为什么会有-1这个优先级?
-1 是 DEADLINE类进程来说固定值,采用EDF调度策略,即对应SCHED_DEADLINE这个策略。比RT进程和normal进程的优先级还要高,在规定的期限内,cpu必须要花指定的时间在本进程上。
为什么表示动态优先级需要两个值prio和normal_prio?
调度器会考虑的优先级则保存在prio. 由于在某些情况下内核需要暂时提高进程的优先级, 因此需要用prio表示. 由于这些改变不是持久的, 因此静态优先级static_prio和普通优先级normal_prio不受影响.
rt_priority数值越大, 实时进程优先级越高, rt_priority 与 prio 如何对应?
在内核代码里有时候会这样调整一个进程的优先级,这里sched_priority优先级指的是rt_priority,越大优先级越高
struct sched_param param = { .sched_priority = 2 }; rv = sched_setscheduler(current, SCHED_RR, ¶m);其转化代码在这块prio = MAX_RT_PRIO-1 - p->rt_priority;即:prio = 99 - rt_priority
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; // 99 - rt_priority else prio = __normal_prio(p); return prio; }在用户空间,进程优先级有两种含义:nice value和scheduling priority。对于普通进程而言,进程优先级就是nice value,从-20(优先级最高)~19(优先级最低),通过修改nice value可以改变普通进程获取cpu资源的比例。随着实时需求的提出,进程又被赋予了另外一种属性scheduling priority,而这些进程被称为实时进程。实时进程的优先级的范围可以通过sched_get_priority_min和sched_get_priority_max,对于linux而言,实时进程的scheduling priority的范围是1(优先级最低)~99(优先级最高)。当然,普通进程也有scheduling priority,被设定为0。
ps ps看到的优先级是越大优先级越高systrace 越小优先级越高top 小于99会标为RT,[100~149] --> [-20 ~ 19]ps -e -o pri,rtprio,cmd用户空间优先级
在用户空间,进程优先级有两种含义:nice value和scheduling priority。对于普通进程而言,进程优先级就是nice value,从-20(优先级最高)~19(优先级最低),通过修改nice value可以改变普通进程获取cpu资源的比例。随着实时需求的提出,进程又被赋予了另外一种属性scheduling priority,而这些进程被称为实时进程。实时进程的优先级的范围可以通过sched_get_priority_min和sched_get_priority_max,对于linux而言,实时进程的scheduling priority的范围是1(优先级最低)~99(优先级最高)。当然,普通进程也有scheduling priority,被设定为0。
进程优先级查看
systrace 中看到的优先级是越小越高,
在ps -lA看到的优先级是越大优先级越高,ps看到0 - 39对应内核优先级中的100 - 139,而40 - 139 对应内核优先级中的RT优先级0 - 99,实时优先级是越大优先级越高
在内核设置实时调度策略 0~99 越大优先级越高
参考:
Linux进程优先级的处理–Linux进程的管理与调度(二十二)
Linux进程和线程的调度与优先级
Linux调度器:进程优先级
