linux任务优先级
这篇笔记记录了linux任务(指线程而非进程)优先级相关的概念,以及用户态可以用来操作这些优先级的系统调用。
基本概念
调度策略
linux内核中的调度器为任务定义了调度策略,也叫调度类,每个任务同一时刻都有唯一的调度策略,这些调度策略按照优先级从高到低依次为:
- SCHED_DEADLINE
内核在3.14引入了Deadline调度策略,适用于那些需要周期性执行,并且必须在指定时间内完成的任务,其优先级最高。Deadline任务的使用场景较少,不是我们关注的重点。
- SCHED_FIFO、SCHED_RR
采用这两种调度策略的任务叫做RT任务,这两种调度策略的优先级相同。
SCHED_FIFO任务一旦就绪,它会立即抢占比自己优先级低的任务,它一旦开始运行,除非被更高优先级的RT任务抢占,或者自己主动让出CPU,否则它会一直运行,这类任务没有时间片的限制。
SCHED_RR在SCHED_FIFO的基础上增加了时间片约束,它每次至多运行一段时间,之后如果还没有运行完也会让出CPU,继续下一次轮转,所以将Round-robin。
- SCHED_OTHER、SCHED_BATCH、SCHED_IDLE
虽然这是三种调度策略,但是调度器基本上对它们不做区分,采用这三种调度策略的任务叫做普通任务。系统中大多数任务的调度策略都是这一类。这类任务共享CPU时间,由内核大名鼎鼎的CFS算法调度运行。
任务优先级
上面的调度策略决定了任务的第一级优先级,其概念是很清晰的,但是linux对于相同或同一类调度策略下各个任务之间的优先级概念就比较混乱,原因是用户态和内核态对这些优先级的叫法不统一。
用户态角度
对于普通任务,用户态是用nice值来表述它们的优先级的,nice值取值[-20, 19]。nice值越大,表示任务对CPU约nice,其优先级最低。
对于RT任务,用户态称其优先级为调度优先级,其值越大,优先级越高,取值范围为[sched_get_priority_min(2), sched_get_priority_min(2)],在linux上总是返回[1, 99]。
内核态角度
task_struct中定义了如下和优先级有关的字段,下面会介绍这些字段的含义。
struct task_struct {
...int prio, static_prio, normal_prio;unsigned int rt_priority;unsigned int policy;
}
对于普通任务,其用户态的nice值到了内核被转换为静态优先级保存到task_struct的static_prio字段中。下面的NICE_TO_PRIO宏会将用户态的nice值范围从[-20, 19]线性映射到[100, 139]范围,依然是值越小优先级越高。
#define MAX_USER_RT_PRIO 100
#define MAX_RT_PRIO MAX_USER_RT_PRIO// NICE_WIDTH为40,表示nice的等级
#define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH) // 139
#define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2) // 120/** 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)void set_user_nice(struct task_struct *p, long nice)
{
...p->static_prio = NICE_TO_PRIO(nice);
}
对于RT任务,其用户态的调度优先级到了内核会被原封不动的保存到task_struct的rt_priority字段中,我们可以称之为实时优先级。
static void __setscheduler_params(struct task_struct *p,const struct sched_attr *attr)
{
...p->rt_priority = attr->sched_priority;
}
内核态归一化优先级
任务的调度策略和优先级上述几种类型,内核态调度器在处理时将这些不同类型的调度策略和优先级进行了归一化处理,将它们映射到了一个线性区间,并使得它们单调性保持一致。归一化后的任务优先级保存在task_struct的normal_prio字段中。
static inline int __normal_prio(struct task_struct *p)
{return p->static_prio;
}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; // MAX_RT_PRIO值为100,将RT任务的调度优先级单调性进行反转elseprio = __normal_prio(p);return prio;
}
归一化处理过程实现的效果如下图所示:

Deadline任务的normal_prio字段为-1,RT任务的normal_prio字段范围为[0, 100), 普通任务的normal_prio字段的范围为[100, 139),这样归一化优先级可以统一表达所有任务的优先级,并且规定归一化优先级值越小优先级越高。
内核态动态优先级
归一化优先级也不是调度器最终用于调度的优先级,这是因为调度器有时候会针对RT任务临时性的调整其优先级,因此又引入了动态优先级。动态优先级被保存在了task_struct的prio字段中。动态优先级通过effective_prio()函数获取。
/** Calculate the current priority, i.e. the priority* taken into account by the scheduler. This value might* be boosted by RT tasks, or might be boosted by* interactivity modifiers. Will be RT if the task got* RT-boosted. If not then it returns p->normal_prio.*/
static int effective_prio(struct task_struct *p)
{p->normal_prio = normal_prio(p);/** If we are RT tasks or we were boosted to RT priority,* keep the priority unchanged. Otherwise, update priority* to the normal priority:*/if (!rt_prio(p->prio))return p->normal_prio;return p->prio;
}
用户态接口
从系统手册sched(7)中可以看到,linux共提供了如下接口供用户态获取和调整任务的优先级。从下面的介绍中可以看到,不同的接口有其适用范围。
| 接口 | 描述 |
| nice(2) | 调整调用线程的nice值 |
| getpriority(2)、setpriority(2) | 操作进程、进程组或用户的所有进程的nice值 |
| sched_setscheduler(2)、sched_getscheduler(2) | 获取线程的调度策略,设置RT任务的调度策略和调度优先级 |
| sched_setparam(2)、 sched_getparam(2) | sched_setscheduler(2)、sched_getscheduler(2)的变体 |
| sched_setattr(2)、sched_getattr(2) | 同时支持RT任务和普通任务调度策略和优先级的接口,该接口在实现上述接口的所有功能外还有额外的扩展功能 |
nice(2)
将调用线程的nice值加上参数inc,所以正的inc可以降低调用线程的优先级,负的inc可以提高调用线程的优先级。
int nice(int inc);
线程的nice值不是可以随意调整的,其可设置的上限受getrlimit(2)中的RLIMIT_NICE值限制。RLIMIT_NICE的取值范围为[1, 40],假设RLIMIT_NICE的配置为rlimit_cur,那么可设置的nice值上限为20 - rlimit_cur。
getpriority(2)、setpriority(2)
这两个接口用于获取和设置任务的nice值。which和who指定了要操作的任务范围,具体有:
- which=PRIO_PROCESS,who=PID。任务范围为进程中所有线程;
- which=PRIO_PGRP,who=进程组长PID。任务范围为进程组中所有线程;
- which=PRIO_USER,who=UID。任务范围为该用户的所有线程;
可以看到,这两个接口的功能比nice(2)要更加的强大和灵活。
int getpriority(int which, id_t who);
int setpriority(int which, id_t who, int prio);
同样的,nice值的可设置上限受getrlimit(2)中的RLIMIT_NICE值限制。
sched_setscheduler(2)、sched_getscheduler(2)
当用sched_setscheduler(2)将线程的调度策略修改为普通任务时,其param->sched_priority必须为0,即该接口不能设置普通任务的nice值。当用它将线程的调度策略修改为RT任务时,可以用param->sched_priority为RT任务指定调度优先级。
sched_getscheduler(2)可以用来获取线程的调度策略。
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
int sched_getscheduler(pid_t pid);struct sched_param {...int sched_priority;...
};
这两个接口的pid为0时,表示操作的时调用线程。
sched_setparam(2)、 sched_getparam(2)
这组接口就是sched_setscheduler(2)、sched_getscheduler(2)的变体。
int sched_setparam(pid_t pid, const struct sched_param *param);
int sched_getparam(pid_t pid, struct sched_param *param);
sched_setattr(2)、sched_getattr(2)
这两个接口是linux特有的,并非POSIX接口,它们支持所有类型任务的调度策略和优先级调整。
int sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags);
int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags);struct sched_attr {u32 size; /* Size of this structure */u32 sched_policy; /* Policy (SCHED_*) */u64 sched_flags; /* Flags */s32 sched_nice; /* Nice value (SCHED_OTHER, SCHED_BATCH) */u32 sched_priority; /* Static priority (SCHED_FIFO, SCHED_RR) *//* Remaining fields are for SCHED_DEADLINE */u64 sched_runtime;u64 sched_deadline;u64 sched_period;
};
相关文章:
linux任务优先级
这篇笔记记录了linux任务(指线程而非进程)优先级相关的概念,以及用户态可以用来操作这些优先级的系统调用。 基本概念 调度策略 linux内核中的调度器为任务定义了调度策略,也叫调度类,每个任务同一时刻都有唯一的调…...
JVM内存模型概述
这里主要分为五大块,分别是:本地方法栈、方法区、java堆、程序计数器和java栈。其中重点是方法区、java堆和java栈。 下面就把各个区域的性质总结一下:(说明,下面的只是结论,没有详细的对各个内存块进行详细…...
【JavaEE】CAS -- 多线程篇(7)
CAS 1. 什么是 CAS2. CAS 伪代码3. CAS 是怎么实现的4. CAS的应用4.1 实现原子类4.2 实现自旋锁 5. CAS 的 ABA 问题 1. 什么是 CAS CAS: 全称Compare and swap,字面意思:”比较并交换“能够比较和交换 某个寄存器中的值和内存中的值, 看是否相等, 如果相等, 则把另…...
18-spring 事务
文章目录 1. xml和注解配置方式的对象2.spring事务传播特性3. 注解事务的初始化流程4. 创建事务信息流程图5. 事务回滚流程图 1. xml和注解配置方式的对象 2.spring事务传播特性 事务传播行为类型说明PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务…...
Qt窗体设计的布局
本文介绍Qt窗体的布局。 Qt窗体的布局分为手动布局和自动布局,手动布局即靠手工排布各控件的位置。而自动布局则是根据选择的布局类型自动按此类型排布各控件的位置,使用起来比较方便,本文主要介绍Qt的自动布局。 1.垂直布局 垂直布局就是…...
分布式锁 - 理论篇
一、为什么需要分布式锁 二、分布式锁实现 1.分布式锁演进 - 基本原理 我们可以同时去一个地方“占坑”,如果占到,就执行逻辑。否则就必须等待,直到释放锁。“占坑”可以去redis,可以去数据库,可以去任何大家都能访…...
复杂的菱形继承及菱形虚拟继承(详解)
复杂的菱形继承及菱形虚拟继承 复杂的菱形继承及菱形虚拟继承虚拟继承解决数据冗余和二义性的原理笔试面试题 复杂的菱形继承及菱形虚拟继承 单继承:一个子类只有一个直接父类时称这个继承关系为单继承 多继承:一个子类有两个或以上直接父类时称这个继…...
【快捷测试模型是否可以跑通】设置一张图片的张量形式,送入自己写的模型进行测试
文章目录 1. 1. import torch.nn as nn import torch from einops import rearrange, repeat from einops.layers.torch import Rearrange import torch.nn.functional as Fclass PreNorm(nn.Module):def __init__(self, dim, fn):super().__init__()self.norm nn.LayerNorm(…...
软考系列(系统架构师)- 2019年系统架构师软考案例分析考点
试题一 软件架构(架构风格、质量属性) 【问题1】(13分) 针对用户级别与折扣规则管理功能的架构设计问题,李工建议采用面向对象的架构风格,而王工则建议采用基于规则的架构风格。请指出该系统更适合采用哪种…...
安防视频监控系统EasyCVR视频汇聚存储平台定制化开发:新增kafka配置
安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台可拓展性强、…...
C++设计模式_08_Factory Method工厂方法模式
文章目录 1. “对象创建模式”模式1.1 典型模式 2. 动机(Motivation)3. 代码演示Factory Method工厂方法模式3.1 常规方法3.2 面向接口的编程3.2.1 FileSplitter1.cpp3.2.2 MainForm1.cpp 3.3 Factory Method工厂方法3.3.1 ISplitterFactory.cpp3.3.2 Ma…...
【TensorFlow1.X】系列学习笔记【基础一】
【TensorFlow1.X】系列学习笔记【基础一】 大量经典论文的算法均采用 TF 1.x 实现, 为了阅读方便, 同时加深对实现细节的理解, 需要 TF 1.x 的知识 文章目录 【TensorFlow1.X】系列学习笔记【基础一】前言线性回归非线性回归逻辑回归总结 前言 本篇博主将用最简洁的代码由浅入…...
Linux 基础操作手记三(内存篇)
Linux 基础操作手记三 释放内存虚拟机彻底无网络测试网速设置虚拟内存交换空间未使用虚拟机设置虚拟内存无法开机问题GParted - 分配内存系统盘扩容自己 释放内存 sync && echo 3 > /proc/sys/vm/drop_caches 虚拟机彻底无网络 还原默认设置,静静的等待…...
NodeJS的初使用,以及引入第三方插件和安装淘宝镜像的教程
NodeJs 命令 npm init -y 生成package.json文件npm i jquery --save–dev 开发依赖(jQuery后面还可以跟模块,可以有多个)npm i jquery --save 生产依赖npm i jquery --D 开发依赖npm uninstall jquery 卸载删除npm i 把删掉的模块,全部重新加载回来 1.介绍 1.什么是NodeJs?…...
Java读取文件的N种方法
1.概述 在这篇文章里, 我们将探索不同的方式从文件中读取数据。 首先, 学习通过标准的的Java类,从classpath、URL或者Jar中加载文件。 然后,学习通用BufferedReader, Scanner, StreamTokenizer, DataInputStream, SequenceInput…...
子类的构造与析构过程
一、简介 父类,也称基类,其构造方法和析构方法不能被继承; 子类,也称派生类,继承父类的方法和属性,但要加入新的构造和析构函数。 二、构造与析构过程 构造:先调用父类——>再调用子类 析构&…...
位运算相关笔记
位运算 Part 1:基础 左移:左移一位,相当于某数乘以 2 2 2。左移 x x x位,相当于该数乘以 2 x 2^x 2x。 右移:右移一位,相当于某数除以 2 2 2。右移 x x x位,相当于该数除以 2 x 2^x 2x。 与运算&…...
uniapp 安装 u-view 组件库
u-view 组件库安装教程:https://uviewui.com/components/install.html 注:以下使用 HBuilderx 安装 u-view 2.0 版本,不适用于其它版本。 1.安装 u-view 组件库 2、注册并登录 HBuilderx 账号,点击下载 u-view 组件库。 3、点击…...
Go 语言的成功案例:谁在使用 Go?
Go 语言,也被称为 Golang,是一门由Google开发的开源编程语言。自从2009年首次亮相以来,它在编程社区中崭露头角,并吸引了越来越多的开发者和组织。Go 以其高效的并发性、出色的性能和简单易懂的语法而闻名。在本文中,我…...
UG\NX二次开发 实时查看 NX 日志文件
文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 感谢粉丝订阅 感谢 a18037198459 订阅本专栏,非常感谢。 简介 实时查看 NX 日志文件,有助于分析保存时间等。打开WindowsPowerShell并实时获取日志文件内容的小功能。 效果 代…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
