Linux --进程优先级

概念

  什么是进程优先级,为什么需要进程优先级,怎么做到进程优先级这是本文需要解释清楚的。

  优先级的本质其实就是排队,为了去争夺有限的资源,比如cpu的调度。cpu资源分配的先后性就是指进程的优先级。优先级高的进程有优先执行的,配置进程优先级对多任务环境的Linux很有用,可以改善系统的性能。在Linux中进程的PCB也就是task_struct中优先级属性是有几个int类型的数字来表示的,数字越小优先级越高。这里我们可以查看一个进程的优先级和修改。我们用ps -l指令可以看到以下几个数据

UID : 代表执⾏者的⾝份
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍⽣⽽来的,亦即⽗进程的代号
PRI :代表这个进程可被执⾏的优先级,其值越⼩越早被执⾏
NI :代表这个进程的nice值
  
  PRI也还是⽐较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执⾏的先后顺序,此
值越⼩进程的优先级别越⾼ 。 那NI呢?就是我们所要说的nice值了,其表⽰进程可被执⾏的优先级的修正数值 PRI值越⼩越快被执⾏,那么加⼊nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice 这样,当nice值为负值的时候,那么该程序将会优先级值将变⼩,即其优先级会变⾼,则其越快被执⾏所以,调整进程优先级,在Linux下,就是调整进程nice值 nice其取值范围是-20⾄19,⼀共40个级别。这里的PRY(old)其实是默认初始PRI的意思。
  ⽤top命令更改已存在进程的nice: top,进⼊top后按“r”‒>输⼊进程PID‒>输⼊nice值

  

  这里可以看到,PRI为39 NI值为19,这是我修改以后的数值,原本是PRI 20 NI 0,即使我输入修改100但是最后值修改了19,说明修改NI值是有范围的 ,这是为了进程调度尽量公平,不会出现个别极端进程,为什么是在这40的范围内后续我们会讲到。

进程切换

  有了优先级就是为了在进程切换的时候进行排序,那么什么是进程切换?进程切换的核心其实就是保存上下文数据恢复上下文数据,那么什么是上下文数据,容我慢慢叙说。一个进程被被cpu调度的时候,此时它的PCB就是现在调度队列的当前节点,在CPU内部有一套寄存器来储存代码和数据,其中的eip来储存当前执行指令的下一地址,ir存储的是当前需要执行的指令,控制器先ir读指令执行,执行完毕又会反馈给eip寄存器。此时储存在寄存器中的代码和数据就是上下文数据。当前进程的时间片到了即将被切换的时候,它会将上下文数据储存到PCB中的一个tss_struct结构体中,方便下次切换回来的时候能够知道上一次运行到了哪里,恢复寄存器中的数据,每个程序在进程切换的时候都需要做这个事情,因为寄存器只有一套,这种行为是对进程代码数据运行的一种保护,如果不做保护就无法进行调度与切换。

  这里可以参考Linux0.11的内核代码发现上下文数据确实是保存在tss之中,但是在现在的内核中由于保护算法已经过于复杂了,没有十章八章难以叙述,所以而且不方便观察

Linux真实调度算法

  说了这么多优先级的本质还是为了更好的了解Lniux调度算法。这个算法并不是简单的FIFO调度,cpu在调度进程时会在一个runqueue结构体中选择需要调度的进程,这个runqueue主要由一个有两个元素queue结构体数组,两个指向queue结构体数组的指针,*active和*expored即活跃的和过期的,以下用示意图说明。

  

  我们可以看到这这两个数组的元素的结构体时由一个int 类型的nr_active,和一个有五个元素int类型的bitmap数组组成的。*active和*expored指针分别指向这两个数组元素,cpu调度时只会从活跃指针这个结构体中的queue队列来调度进程,这个队列通常前一百位是不用的,而后四十位就是对应我们上面所提到的优先级范围,40这个范围就是因为队列中只有四十个位置是储存进程的。这个队列每个元素下又挂着一个哈希桶,所以每个相同优先级的进程都会被挂在同一个桶中,调度的时候按照队列先进先出的规则被调度,当这个优先级桶的元素空了cpu才会调度下一个优先级的进程。其中这里的nr_active是一个计数器,记录当前队列中还有多少个进程,bitmap是为了提高cpu调度效率而存在的,它用5*32个比特位来表示当前调度queue队列中哪个优先级有进程再去这个地方调度进程,而不是进行遍历队列查找再调度。过期队列上放置的进程,都是时间⽚耗尽的进程和新插入的进程,当活动队列上的进程都被处理完毕之后,对过期队列的进程进⾏时间⽚重新计算。active指针永远指向活动队列, expired指针永远指向过期队列, 可是活动队列上的进程会越来越少,过期队列上的进程会越来越多,因为进程时间⽚到期时⼀直都存在的,所以在合适的时候交换active指针和expired指针的内容,就相当于有具有了⼀批新的活动进程。这个合适的时候就是当活跃进程nr_active计数器为0的时候,此时两个两个队列就会被调换开始新一轮的调度。注意结束的进程是不会进入过期队列的,而是会被父进程接管并释放。

   在系统当中查找⼀个最合适调度的进程的时间复杂度是⼀个常数,不随着进程增多⽽导致时间成 本增加,我们称之为进程调度O(1)算法!Linux中的内核调度算法就是进程调度O(1)算法。

  顺便提到一点Linux中的task_struct中的链式结构并不是和普通双链表那样将节点和属性放在一起,它的链表节点中只有next节点和prev节点,然后在task_struct中和其他属性一起储存。这样做的好处是能够让一个task_struct在多个队列(调度和阻塞)中存在,而不需要将相同的进程属性放在不同的链表之中再链接。如图所示

 

补充 

  那么有的同学会问了只有链表节点如何访问数据,每个数据类型的偏移量相对于结构体指针是固定的,我们可以通过链表节点的地址和偏移量来找到当前结构体指针再访问其他的数据。我们可以通过offseto这个宏来获得该成员相对于0地址的偏移。

#define offsetof(type, member) ((size_t)&(((type *)0)->member))

这里有一个代码可以方便大家理解具体过程

#include <iostream>#define offsetof(type, member) ((size_t)&(((type *)0)->member))
using namespace std;int main()
{struct A{int a;int b;float c;double d;};A instanceA; // Renamed variable to avoid conflict with struct namecout << " 结构体A的地址 : " << &instanceA << endl;cout << " 成员a的地址  :" << &instanceA.a << " 偏移量 :" << offsetof(A, a) << endl;cout << " 成员b的地址  :" << &instanceA.b << " 偏移量 :" << offsetof(A, b) << endl;cout << " 成员c的地址  :" << &instanceA.c << " 偏移量 :" << offsetof(A, c) << endl;cout << " 成员d的地址  :" << &instanceA.d << " 偏移量 :" << offsetof(A, d) << endl;return 0;
}

  我们可以看到两次运行的各个成员地址都不一样,但是偏移量都是相同的 

  然后我们就可以通过这样的方法来找到对象本身从而访问其他的数据

int main() {A instanceA;int* pB = &instanceA.b;A* pStruct = (A*)((char*)pB - offsetof(A, b));cout << "instanceA 地址: " << &instanceA << endl;cout << "通过成员b地址和偏移量得到的结构体地址: " << pStruct << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82574.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React 性能监控与错误上报

核心问题与技术挑战 现代 React 应用随着业务复杂度增加&#xff0c;性能问题和运行时错误日益成为影响用户体验的关键因素。没有可靠的监控与错误上报机制&#xff0c;我们将陷入被动修复而非主动预防的困境。 性能指标体系与错误分类 关键性能指标定义 // performance-me…

芒果深度学习检测:开启农业新视界(猫脸码客第230期)

芒果深度学习检测&#xff1a;开启农业新视界 一、引言 芒果作为热带水果中的“明星”&#xff0c;在全球水果市场占据着重要地位&#xff0c;拥有广泛的市场需求和可观的经济价值。伴随人们生活品质的提升&#xff0c;对芒果品质的要求也愈发严苛。芒果产业规模持续扩张&#…

PDF文件转换之输出指定页到新的 PDF 文件

背景 一份 PDF 学习资料需要打印其中某几页&#xff0c;文件有几百兆&#xff0c;看到 WPS 有PDF拆分功能&#xff0c;但是需要会员&#xff0c;开了一个月会员后完成了转换。突然想到&#xff0c;会员到期后如果还要拆解的话&#xff0c;怎么办呢&#xff1f;PDF 文件拆解功能…

【计网】SW、GBN、SR、TCP

目录 三种可靠传输机制&#xff08;数据链路层&#xff09; 停止-等待&#xff08;Stop and Wait&#xff0c;SW&#xff09;协议 回退N帧&#xff08;Go-back-N&#xff0c;GBN&#xff09;协议 选择重传&#xff08;Selective Repeat&#xff0c;SR&#xff09;协议 传输…

Go的隐式接口机制

正确使用Interface 不要照使用C/Java等OOP语言中接口的方式去使用interface。 Go的Interface的抽象不仅可以用于dynamic-dispatch 在工程上、它最大的作用是&#xff1a;隔离实现和抽象、实现完全的dependency inversion 以及interface segregation(SOLID principle中的I和D)。…

Async-profiler 内存采样机制解析:从原理到实现

引言 在 Java 性能调优的工具箱中&#xff0c;async-profiler 是一款备受青睐的低开销采样分析器。它不仅能分析 CPU 热点&#xff0c;还能精确追踪内存分配情况。本文将深入探讨 async-profiler 实现内存采样的多种机制&#xff0c;结合代码示例解析其工作原理。 为什么需要内…

Android 颜色百分比对照

本文就是简单写个demo,打印下颜色百分比的数值.方便以后使用. 1: 获取透明色 具体的代码如下: /*** 获取透明色* param percent* param red* param green* param blue* return*/public static int getTransparentColor(int percent, int red, int green, int blue) {int alp…

MPLS-EVPN笔记详述

目录 EVPN简介: EVPN路由: 基本四种EVPN路由 扩展: EVPN工作流程: 1.启动阶段: 2.流量转发: 路由次序整理: 总结: EVPN基本术语: EVPN表项: EVPN支持的多种服务模式: 简介: 1.Port Based: 简介: 配置实现: 2.VLAN Based: 简介: 配置实现: 3.VLAN Bundle: 简…

SpringBoot自定义线程池详细教程

文章目录 1. 线程池基础概念1.1 什么是线程池1.2 Java线程池核心参数1.3 线程池执行流程 2. SpringBoot中的线程池2.1 SpringBoot默认线程池2.2 SpringBoot异步任务基础 3. 自定义线程池配置3.1 配置文件方式3.2 Java配置方式3.3 线程池工厂配置 4. 异步任务实际应用4.1 业务服…

智能快递地址解析接口如何用PHP调用?

一、什么是智能快递地址解析接口 随着互联网技术的普及和电子商务的迅猛发展&#xff0c;网购已成为现代人日常生活的重要组成部分。然而&#xff0c;在这个便捷的背后&#xff0c;一个看似不起眼却影响深远的问题正悄然浮现——用户填写的快递地址格式混乱、信息不全甚至错漏…

概率分布,支撑AI算法的数学基石

概率分布,是现代人工智能(AI)算法不可或缺的数学语言。它不仅描述了数据中的不确定性,更揭示了机器学习模型背后的本质运作机制。本文将带你深入了解概率分布的数学本质,以及它在监督学习、深度学习、生成模型等核心AI领域的关键作用,揭秘概率论如何成为AI理论和实践的强…

2025年Splunk的替代方案:更智能的安全选择

在安全信息和事件管理&#xff08;SIEM&#xff09;领域&#xff0c;2025年的竞争愈发激烈。Splunk凭借其强大的功能和稳定性长期占据市场主导地位&#xff0c;但其高昂的成本、复杂性和扩展性挑战促使许多企业转向其他解决方案。无论是初创公司、快速发展的中型企业&#xff0…

(10)Fiddler抓包-Fiddler如何设置捕获Firefox浏览器的Https会话

1.简介 经过上一篇对Fiddler的配置后&#xff0c;绝大多数的Https的会话&#xff0c;我们可以成功捕获抓取到&#xff0c;但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话&#xff0c;需要我们更进一步的配置才能捕获到会话进行抓包。 2.环境 1.环境是Windows 10版…

simulink mask的使用技巧

1.mask界面布局 1.1如何调整控件的位置和控件大小&#xff1f; 反正2020a是调不了&#xff0c; 找了好久&#xff0c;只能是调布局&#xff0c;例如你要调成下面这样&#xff1a; 第一个控件的iTem location属性选择New row 后面跟着的几个和第一个同一行的空间属性选择Cu…

Go中MAP底层原理分析

MAP底层原理分析 参考 https://golang.design/go-questions/map/principalmap | Golang 中文学习文档 先来看一下map结构体&#xff0c;&#xff08;runtime.hmap结构体就是代表着 go 中的map&#xff0c;与切片一样map的内部实现也是结构体&#xff09; type hmap struct {/…

#开发环境篇:postMan可以正常调通,但是浏览器里面一直报403

本地header代理下面内容即可 headers: { // 添加必要的请求头 ‘Host’: ‘服务端域名’, ‘Origin’: https://服务端域名, ‘Referer’: https://服务端域名 }, devServer: {// 本地开发代理API地址proxy: {^/file: {target: https://服务端域名,changeOrigin: true, // 是否…

【论文阅读 | PR 2024 |ICAFusion:迭代交叉注意力引导的多光谱目标检测特征融合】

论文阅读 | PR 2024 |ICAFusion&#xff1a;迭代交叉注意力引导的多光谱目标检测特征融合 1.摘要&&引言2.方法2.1 架构2.2 双模态特征融合&#xff08;DMFF&#xff09;2.2.1 跨模态特征增强&#xff08;CFE&#xff09;2.2.2 空间特征压缩&#xff08;SFS&#xff09;…

效率、便捷、安全:智慧充电桩一站式解决方案如何重塑新能源充电体验?

在新能源浪潮席卷全球的背景下&#xff0c;电动汽车的普及对充电基础设施提出了更高要求。传统充电模式因效率低、操作繁琐、安全隐患等问题&#xff0c;难以满足用户需求。智慧充电桩一站式解决方案应运而生&#xff0c;通过技术创新将效率、便捷与安全融为一体&#xff0c;彻…

杰发科技AC7840——Timer修改重装载值

需要在运行过程中修改定时器的中断时间 int main(void) {SystemClock_Config(); /*时钟初始化*/GPIO_LedInit(); /*GPIO初始化*/TIMER_Init(); /*定时器初始化*/InitDebug(); …

https和http有什么区别-http各个版本有什么区别

http和 https的区别 HTTP&#xff08;超文本传输协议&#xff09;和 HTTPS&#xff08;安全超文本传输协议&#xff09;是两种用于在网络上传输数据的协议&#xff0c;它们的主要区别在于安全性&#xff1a; HTTP&#xff08;Hypertext Transfer Protocol&#xff09;&#x…