Linux 中采用了两种不同的优先级范围,一种是 nice 值,一种是实时优先级。在上一篇粗略的说了一下 nice 值和实时优先级,仍有不少疑问,本文来详细说明一下进程优先级。linux 内核版本为 linux 2.6.34 。

进程优先级的相关信息,存放在进程描述符 task_struct 中:

structtask_struct {

...intprio, static_prio, normal_prio;

unsignedintrt_priority;

...

}

可以看到,有四种进程优先级: prio、static_prio、normal_prio 和 rt_priority,它们的具体定义在 kernel/sched.c 中,在介绍这四种优先级之前,先介绍一下以下宏定义:

/*linux-kernel 2.6.34 /include/linux/sched.h*/

/** 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.

*

* 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 + 40)

#define DEFAULT_PRIO (MAX_RT_PRIO + 20)    //默认优先级,对应 nice 值为 0 的静态优先级

1、prio 动态优先级

prio 的值是调度器最终使用的优先级数值,即调度器选择一个进程时实际选择的值。prio 值越小,表明进程的优先级越高。prio  值的取值范围是 0 ~ MAX_PRIO,即 0 ~ 139(包括 0 和 139),根据调度策略的不同,又可以分为两个区间,其中区间 0 ~ 99 的属于实时进程,区间 100 ~139 的为非实时进程。用语言不好描述,我们通过内核代码来详细描述 prio:

/*linux-kernel 2.6.34 /kernel/sched.c*/#include"sched_idletask.c"#include"sched_fair.c"#include"sched_rt.c"#ifdef CONFIG_SCHED_DEBUG

#include"sched_debug.c"

#endif

/** __normal_prio - return the priority that is based on the static prio*/

static inline int __normal_prio(struct task_struct *p)    //_normal_prio 函数,返回静态优先级值

{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)    //normal_prio 函数

{intprio;if (task_has_rt_policy(p))                 //task_has_rt_policy 函数,判断进程是否为实时进程,若为实时进程,则返回1,否则返回0

prio = MAX_RT_PRIO-1 - p->rt_priority;        //进程为实时进程,prio 值为实时优先级值做相关运算得到: prio = MAX_RT_PRIO -1 - p->rt_priority

elseprio= __normal_prio(p);                //进程为非实时进程,则 prio 值为静态优先级值,即 prio = p->static_prio

returnprio;

}/** 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)       //effective_prio 函数,计算进程的有效优先级,即prio值,这个值是最终调度器所使用的优先级值

{

p->normal_prio = normal_prio(p);              //计算 normal_prio 的值

/** 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;                  //若进程是非实时进程,则返回 normal_prio 值,这时的 normal_prio = static_prio

return p->prio;                         //否则,返回值不变,依然为 prio 值,此时 prio = MAX_RT_PRIO -1 - p->rt_priority

}/*********************** 函数 set_user_nice ****************************************/

void set_user_nice(struct task_struct *p, longnice)

{

....

p->prio = effective_prio(p);               //在函数 set_user_nice 中,调用 effective_prio 函数来设置进程的 prio 值

....

}

从上面代码中我们知道,当进程为实时进程时, prio 的值由实时优先级值(rt_priority)计算得来;当进程为非实时进程时,prio 的值由静态优先级值(static_prio)得来。即:

prio = MAX_RT_PRIO - 1 - rt_priority    // 进程为实时进程

prio = static_prio          // 进程为非实时进程

简单计算上面的两个式子,可以知道,prio 值的范围是 0 ~ 139 。

2、static_prio 静态优先级

静态优先级不会随时间改变,内核不会主动修改它,只能通过系统调用 nice 去修改 static_prio,如下:

/** Convert user-nice values [ -20 ... 0 ... 19 ]

* to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],

* and back.*/

#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20)

#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20)

#define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio)

/** 'User priority' is the nice value converted to something we

* can work with better when scaling various scheduler parameters,

* it's a [ 0 ... 39 ] range.*/

#define USER_PRIO(p) ((p)-MAX_RT_PRIO)

#define TASK_USER_PRIO(p) USER_PRIO((p)->static_prio)

#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO))/********************* 函数 set_user_nice *****************************/

p->static_prio = NICE_TO_PRIO(nice);     //当有需要时,系统会通过调用 NICE_TO_PRIO() 来修改 static_prio 的值

由上面代码知道,我们可以通过调用 NICE_TO_PRIO(nice) 来修改 static_prio  的值, static_prio 值的计算方法如下:

static_prio = MAX_RT_PRIO + nice +20

MAX_RT_PRIO 的值为100,nice 的范围是 -20 ~ +19,故 static_prio 值的范围是 100 ~ 139。 static_prio 的值越小,表明进程的静态优先级越高。

3、normal_prio 归一化优先级

normal_prio 的值取决于静态优先级和调度策略,可以通过 _setscheduler 函数来设置 normal_prio 的值 。对于非实时进程,normal_prio 的值就等于静态优先级值 static_prio;对于实时进程,normal_prio = MAX_RT_PRIO-1 - p->rt_priority。代码如下:

static inline int normal_prio(struct task_struct *p)    //normal_prio 函数

{intprio;if (task_has_rt_policy(p))                 //task_has_rt_policy 函数,判断进程是否为实时进程,若为实时进程,则返回1,否则返回0

prio = MAX_RT_PRIO-1 - p->rt_priority;        //进程为实时进程,prio 值为实时优先级值做相关运算得到: prio = MAX_RT_PRIO -1 - p->rt_priority

elseprio= __normal_prio(p);                //进程为非实时进程,则 prio 值为静态优先级值,即 prio = p->static_prio

returnprio;

}

4、rt_priority 实时优先级

rt_priority 值的范围是 0 ~ 99,只对实时进程有效。由式子:

prio = MAX_RT_PRIO-1 - p->rt_priority;

知道,rt_priority 值越大,则 prio 值越小,故 实时优先级(rt_priority)的值越大,意味着进程优先级越高。

rt_priority 的值也是取决于调度策略的,可以在 _setscheduler 函数中对 rt_priority 值进行设置。

内容来源于网络如有侵权请私信删除

linux 系统调用 优先级,Linux内核学习笔记(6)-- 进程优先级详解(prio、static_prio、normal_prio、rt_priority)...相关推荐

  1. ELK学习笔记之Logstash详解

    0x00 Logstash概述 官方介绍:Logstash is an open source data collection engine with real-time pipelining cap ...

  2. expect学习笔记及实例详解【转】

    1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示: 1.1 首行加上/usr/bin/expect 1.2 spawn: 后面加上需要执行的shell命令,比如说 ...

  3. Java中大数据数组,Java基础学习笔记之数组详解

    摘要:这篇Java开发技术栏目下的"Java基础学习笔记之数组详解",介绍的技术点是"java基础学习笔记.基础学习笔记.Java基础.数组详解.学习笔记.Java&qu ...

  4. oracle scn 重置,学习笔记:Oracle SCN详解 SCN与Oracle数据库恢复的关系

    天萃荷净 分享一篇关于Oracle SCN的详解,介绍SCN与Oracle数据库恢复的关系和SCN在数据库中的作用 一.为什么需要System checkpoint SCN号与Datafile Che ...

  5. CSS入门学习笔记(案例+详解)

    CSS入门学习笔记 一.CSS简介 1.什么是CSS? 2.为什么使用CSS? 3.CSS的作用 二.CSS语法 1.CSS基础语法 2.CSS注释语法 3.CSS应用方法 三.CSS选择器 1.元素 ...

  6. PyQt5学习笔记——一文详解QObject

    QObject详解笔记1 一.简介 QObject是所有Qt对象的基类 二.功能作用 2.1 对象名称.属性 2.1.1 API setObjectName("唯一名称") 给QT ...

  7. shell入门学习笔记-12-命令详解: echo与printf

    系列目录与参考文献传送门: shell入门学习笔记-序章 命令详解 admindeMacBook-Pro:myshell admin$ type cd cd is a shell builtin ad ...

  8. CoAP学习笔记——CoAP格式详解

    0 前言 CoAP是受限制的应用协议(Constrained Application Protocol)的代名词.在当前由PC机组成的世界,信息交换是通过TCP和应用层协议HTTP实现的.但是对于小型 ...

  9. shell入门学习笔记-15-命令详解: 三剑客之一awk-分支语句、数组

    系列目录与参考文献传送门: shell入门学习笔记-序章 awk分支控制 if admindeMacBook-Pro:~ admin$ seq 5 |awk '{if($0%2) print $0}' ...

最新文章

  1. Python 之父谈 Python
  2. 搜索和搜索形式(SEARCHING and its forms)
  3. android drawpath大小,Android Path和PathMeasure
  4. 【java实训课】web网页相关知识点总结
  5. 2021天猫双11:阿里巴巴业务已全部跑在阿里云上
  6. android 拼图课程设计,拼图游戏设计_课程设计报告.docx
  7. 准大学生的实用省钱小技巧
  8. 把房子交给“我爱我家”后,我都不敢再进去了
  9. mysql返回前2行_取得前一次MySQL操作所影响的记录行数
  10. silverlight实现图片局部放大效果
  11. 最牛通达信短线超强波段主图指标公式 源码
  12. 黑客帝国中的代码雨写法
  13. 连接数据库出现错误代码为18456
  14. 前端工程师年终总结(2019)
  15. 考试系统设计oracle,在线考试系统的设计与实现|毕业设计源代码|论文开题报告|Oracle...
  16. win10应用已被java安全阻止,win10系统不能运行java提示“应用程序已被安全设置被阻止”的图文方法...
  17. Codeforces A. XXXXX (数学 / 双指针) (Round #649 Div.2)
  18. 基于凸松弛算法的电力市场策略研究(Matlab代码实现)
  19. 计算机无法识别ipad2,iTunes无法识别iPad mini怎么办【解决方法】
  20. 谷歌浏览器和火狐浏览器的12px字体显示大小不一样

热门文章

  1. jsp java方法调用_jsp怎么调用java方法
  2. 计算机网络A习题(2)
  3. `算法竞赛题解` `LeetCode` 6126. 设计食物评分系统
  4. Wuss Weapp一款高质量,组件齐全,高自定义的微信小程序 UI 组件库
  5. 【NOIP2017提高A组集训10.22】友谊
  6. 程序报“通常每个套接字地址(协议/网络地址/端口)只允许使用一次”
  7. 计算机excel操作实训报告,计算机基础实验报告电子表格处理.doc
  8. wincc mysql ado_WINCC中使用ADO对象连接数据库 例子 常用属性 方法
  9. sql 连表修改数据
  10. Java酒瓶瓶盖_酒瓶与瓶盖配合常见问题分析