LINUX 进程优先级与调度策略

mac2026-09-30  4

1. 调度策略

//https://android.googlesource.com/kernel/common/+/refs/heads/android-4.14/include/uapi/linux/sched.h ....... /* * Scheduling policies */ #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 #define SCHED_BATCH 3 /* SCHED_ISO: reserved but not implemented yet */ #define SCHED_IDLE 5 #define SCHED_DEADLINE 6 /* 0: 默认的调度策略,针对的是普通进程。 1:针对实时进程的先进先出调度。适合对时间性要求比较高但每次运行时间比较短的进程。 2:针对的是实时进程的时间片轮转调度。适合每次运行时间比较长得进程。 3:针对批处理进程的调度,适合那些非交互性且对cpu使用密集的进程。 SCHED_ISO:是内核的一个预留字段,目前还没有使用 5:适用于SCHED_DEADLINE优先级较低的后台进程。 6:SCHED_DEADLINED在规定的期限内cpu必须要花指定的时间在本进程上。 SCHED_NORMAL和SCHED_BATCH调度普通的非实时进程, SCHED_FIFO和SCHED_RR和SCHED_DEADLINE则采用不同的调度策略调度实时进程, SCHED_IDLE则在系统空闲时调用idle进程. */

可以通过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(优先级最高)

2. 内核优先级表示

2.1 概述

内核使用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)
2.2 内核优先级表示

在内核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, &param);

其转化代码在这块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; }
2.3 各个命令看到优先级

在用户空间,进程优先级有两种含义: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调度器:进程优先级

最新回复(0)