当前位置: 首页 > news >正文

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如果当前没有事务,就新建一个事务&#xf…...

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并实时获取日志文件内容的小功能。 效果 代…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

python/java环境配置

环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色&#xf…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

今日科技热点速览

🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...