一、背景
在工作中,不少同学对nice,priority,schedue策略,实时优先级,普通进程优先级的概念混淆,导致最后的代码可能引入bug,本文将统一进行说明,部分内容参考网络大佬的文章 ,文末标记引用来源。
二、优先级的设定 API及关键结构体
设置调度策略,在linux上,FIFO和RR都是RT 调度策略
#include <pthread.h>
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
//policy: SCHED_FIFO, SCHED_RR, and SCHED_OTHER
设置线程优先级相关API
#include <pthread.h>
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
struct sched_param {
int sched_priority; /* Scheduling priority */
};
一个进程结构体中,优先级相关字段
struct task_struct {
...
int prio;
int static_prio;
int normal_prio;
unsigned int rt_priority;
...
unsigned int policy;
...
};
这些优先级值的关系可以参考后面说明
三、Linux 优先级调度策略及优先级值的含义
不同调度策略的说明:
- SCHED_OTHER 分时调度策略 (normal thread)
- SCHED_FIFO 实时调度策略:先到先得,一旦占用cpu则一直运行,直到有更高优先级任务到达或自己放弃 (RT thread)
- SCHED_RR 实时调度策略:时间片轮转。当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。放在队列尾保证了所有具有相同优先级的RR任务的调度公平(RT thread)
不同优先级关系的说明
详细描述可以参考文末《Linux调度器:进程优先级》
简单的说,先要区分RT 优先级和normal 优先级:
用户空间下
RT 优先级:1~99 (值越大,优先级越高)
normal 优先级: nice 值从 -20(优先级最高) ~ 19(优先级最低) ,nice值是越小优先级越高,默认为0
内核空间中(会对normal和rt 线程优先级 nice值做归一化,对内核来讲都是一个个的task_struct,归一化有利于后面调度策略的计算和选择)
从用户空间的rt优先级值和normal线程的nice值看到,它们的定义似乎是相反的,一个越大代表优先级越高,一个越小优先级越高,怎么归一化呢,实际上内核中是用99 - rt 值进行了反转
normal_priority RT线程优先级:0~99 (注意这里的0~99 和用户空间真实设定的值是相反的关系,用户空间设置rt优先级99,这里就是0)
normal_priority normal线程优先级:100~139 (nice值为 -20,代表这里的100)
nice值 | priority | 内核空间归一化的优先级 | |
---|---|---|---|
普通线程 | -20~19 | 0 | 100~139 |
RT线程 | / | 1~99 | 98~0 (图实际有点小错误,99 不可到达) |
四、工具显示的优先级差异
常见的查看优先级方法:
top
ps -el
atop -s
实验一、一个普通进程下不同工具的显示结果
利用工具chrt来设置调度策略及优先级,如:sudo chrt -r 50 ./hello ---- 设置 SCHED_RR,优先级为50
top
ps -el
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 R 0 5352 5351 95 9 - - 660 - pts/2 00:18:38 hello
atop -s
实验二、一个RT进程不同工具的显示结果
利用nice来调整,如:sudo nice -n 5 ./hello ---设置普通进程 nice值为5
top
ps -el
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 R 0 6917 6916 99 85 5 - 660 - pts/2 00:00:07 hello
atop -s
这些工具显示同一个进程的优先级数值却大不相同,这些值怎么和API 设置的值对应起来?这些值只是工具计算的方式不同导致的,其中和当前内核/userspace设置比较匹配的是atop;
top 在普通进程default PR值是20, 根据nice值做调整,PR取值范围在0~39, 但是在表示rt thread时,全部都是负值, 为-1-rt, 从 -2 ~ -99(这里你会有疑问,rt的值是1~99,还有一个-100怎么没有?实际当rt=99时,这里的PR会显示rt)
ps -el 它的PRI 值取值范围是 -40 ~99 (和内核归一化的值0~139 有-40的差值), 它的值实际和内核归一化的含义一致,只是有-40 的差值;
atop -s 的取值 PRI就是内核归一化的值, RTPR 在线程为rt线程时,显示为用户api设置的值,当为normal线程时为0;
五、总结
linux 下不同工具显示的优先级数值,不同的展示方式给开发者带来了困扰,再叠加用户空间设置优先级值,调度策略,以及内核侧又重新进行了归一化操作,部分工具显示的内核归一化的值,导致这些概念数值困扰了开发者,这里将工具的差异做了一个总结:
工具 | PR | NI | PRI | NICE | RTPR | POLI | |
---|---|---|---|---|---|---|---|
RT线程 | top | -1 - rt | 0无意义 | / | / | / | / |
normal | top | 20 + nice值 | nice值 | / | / | / | / |
RT线程 | ps -el | / | 无意义 | 99 - rt - 40 | / | / | / |
normal | ps -el | / | nice值 | 120 + nice -40 | / | / | / |
RT线程 | atop -s | / | / | 99-rt | rt | rr/fifo | |
normal | atop -s | / | / | 120+nice | nice值 | 0 | normal |
上面表中的rt值和nice值均为用户空间设置的值
参考资源:
Linux调度器:进程优先级
articles/20230802-linux-sched-api.md · aosp-riscv/working-group - Gitee.com
https://mp.weixin.qq.com/s/44Gamu17Vkl77OGV2KkRmQ