♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥

♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥

♥♥♥我们一起努力成为更好的自己~♥♥♥

♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥

♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥

✨✨✨✨✨✨个人主页✨✨✨✨✨✨

        前面我们已经学习了进程的前置知识,今天这一篇博客我们继续来学习进程,准备好了吗~我们发车去探索进程的奥秘啦~🚗🚗🚗🚗🚗🚗

目录

进程优先级😜

基本概念😘

Linux 中的进程优先级😍

PRI 和 NI😜

优先级计算公式😄

查看进程优先级😀

调整进程优先级的方法😋

使用 nice 和 renice 命令🙃

使用 top 命令动态调整😁

使用系统调用 setpriority 和 getpriority👍

总结与对比🐷

进程的竞争性、独立性、并行与并发😊

进程切换(Context Switching)😀

什么是进程切换?😊

为什么会进程切换?❤

进程切换步骤😭

Linux O(1) 调度器😍

理论核心架构😜

调度过程 😜

队列交换 🙃

为什么叫O(1)算法?👌

总结🐷


进程优先级😜

基本概念😘

1. 什么是进程优先级?

    进程优先级(Priority)操作系统调度器用来决定哪个进程先获得 CPU 资源的一种机制优先级高的进程会优先被调度执行。注意优先级与“权限”不同优先级决定的是“谁先谁后”,而权限决定的是“能否访问”。

2. 为什么需要进程优先级?

    资源有限性:CPU 资源有限,而进程数量众多,需要通过优先级合理分配资源。

    系统性能优化:通过调整进程优先级,可以确保关键任务优先执行,提升系统整体性能。

Linux 中的进程优先级😍

PRI 和 NI😜

    PRI(Priority):进程的实际优先级,值越小优先级越高

    NI(Nice):用于调整 PRI 的修正值,用户可通过修改 NI 来间接影响 PRI。

优先级计算公式😄

PRInew​=PRIold​+nice

            nice 的取值范围为 -20 到 19,共 40 个级别【Linux 是一个分时操作系统,这一个范围也保证了一定的公平公正】,过度调高某个进程的优先级可能导致其他进程“饥饿”【其他进程无法得到调度和CPU资源】

            PRI 的范围一般为 60 到 99(Linux 默认范围),Nice 值的 40 个级别(-20 到 19)正好一对一地映射到优先级(PRI)的 40 个级别(60 到 99)上。 NI 是用户可见的、可调整的“输入”,而 PRI 是内核内部实际使用的“输出”值。

查看进程优先级😀

使用 ps -l ps -al 命令

    我们可以发现【ps -l】和【ps -al】查询到的进程是两种不同的结果~这也就是它们的区别所在,我们来看看下面的对比表格~

特性ps -lps -al
显示范围仅当前终端所有终端
用户范围仅当前用户所有用户
进程数量较少较多
终端显示仅当前终端 (pts/0)多个终端 (pts/0, pts/1)

        除此之外,我们还可以发现进程的 PRI 都为 80,NI 都为 0——这正是 Linux 进程调度默认行为的体现~

        在大多数 Linux 系统中,80 是用户进程启动时的默认基准优先级。这个值(具体数值可能因内核版本和发行版略有不同,但 80 非常常见)被设计为调度队列中的一个中间值。这意味着新创建的进程不会天然地拥有很高或很低的优先级,它们在竞争 CPU 时间时处于一个相对公平的起跑线上。

        0 是默认的 Nice 值。Nice 值是用户或系统用来对默认优先级进行微调的修正值。一个为 0 的 NI 值表示“不做任何调整”,所以进程的最终优先级 PRI 就等于默认的基准优先级 80 + 0 = 80

调整进程优先级的方法😋

使用 nicerenice 命令🙃

         nice 用于启动一个进程并指定其 nice 值renice 用于修改已运行进程的 nice 值~

非特权用户只能调低优先级(提高 nice 值),不能调高(降低 nice 值)~

# 启动一个进程(code)并设置 nice 值为 10
nice -n 10 ./code# 修改已运行进程(PID=4340)的 nice 值为 5
renice -n 15 -p 4340

注意事项:普通用户只能降低优先级(增加 NI 值),只有 root 用户才能提高优先级(设置负的 NI 值)。nice 用于启动新进程时设置,renice 用于修改已运行进程的优先级。

使用 top 命令动态调整😁

  1. 命令行输入top;

  2. r

  3. 输入进程 PID;

  4. 输入新的 nice 值。

  5. 按q退出

注意事项:这是交互式实时调整,同样受权限限制(普通用户不能设置负值)【与 renice 命令完全相同。在 top 界面中,如果你是普通用户,尝试输入负值会得到 “Operation not permitted” 的错误】修改仅对进程的当前运行实例有效,进程重启后恢复默认优先级。

使用系统调用 setprioritygetpriority👍

注意事项:需要在程序代码中调用,主要权限限制与命令行相同。必须包含完善的错误处理(如检查返回值),适合在应用程序中实现自适应的优先级管理。

总结与对比🐷

特性nice / renice 命令top 命令系统调用
使用场景命令行、脚本交互式实时监控与调整程序内部集成
控制对象新进程 / 已存在进程已存在进程自身或其他进程(编程控制)
灵活性交互式,中最高,可编程逻辑控制
权限要求普通用户只能降级普通用户只能降级普通用户只能降级
持久性进程运行期间有效进程运行期间有效进程运行期间有效
主要优势简单直接,易于脚本化实时直观,结合系统监控灵活自动化,嵌入程序逻辑

通用重要注意事项

  1. 权限是核心:记住 -20-1 【负值】的区间是 root 的“特权区”。

  2. 公平性:不要滥用高优先级,否则可能导致系统资源饥饿(Starvation),影响其他重要进程和系统整体稳定性。

  3. 非永久性:所有修改都只在进程生命周期内有效,进程重启后设置失效。

进程的竞争性、独立性、并行与并发😊

竞争性多个进程竞争有限的 CPU 资源,优先级用于解决竞争问题

独立性进程之间相互隔离,一个进程的崩溃不会直接影响其他进程

并行多个进程多个 CPU 核心上同时执行

并发多个进程一个 CPU 核心上通过时间片轮转交替执行,宏观上间隔时间很短看似同时运行

进程切换(Context Switching)😀

什么是进程切换?😊

        进程切换是指操作系统将当前正在运行的进程挂起,并恢复另一个进程执行的过程。这个过程也叫做 CPU 上下文切换(CPU Context Switching)

            那么什么是上下文呢?前面对于进程学习,我们简单介绍了一下上下文数据~   接下来我们来看看什么是CPU上下文?

  • 理论:CPU上下文指的是在任务(进程/线程)执行时,CPU寄存器程序计数器在任意时刻的状态。CPU内的寄存器只有一份,但是上下文可以有多份,分别对应不同的进程寄存器存储着进程的临时数据、地址、状态信息程序计数器(PC)存储着下一条要执行的指令地址

  • 比喻:这就像 一个厨师的工作台当前状态——哪些食材正在处理、刀放在哪、火开到多大、菜谱翻到了哪一页。这一切定义了“工作做到哪一步了”。

为什么会进程切换?❤

  • 理论:操作系统为了实现并发(Concurrency)让多个进程在一段时间内“看起来”同时运行。当一个进程的时间片用完、或需要等待I/O操作、或有更高优先级进程就绪时,就需要切换。

  • 比喻:餐厅经理(操作系统)为了保证公平性和效率,规定每个厨师一次只能在厨房工作一段时间(时间片)。时间到了就必须换人,让其他厨师也能用厨房,防止一个厨师霸占厨房。

进程切换步骤😭

  1. 保存上下文 (Save the Context):

    • 理论:将当前进程的CPU寄存器状态全部保存到它的内核栈(Kernel Stack) 中。

    • 比喻:厨师A被叫出厨房前,他必须迅速而准确地在自己的记事本(内核栈) 上记下所有工作状态:“洋葱切了一半,还剩3个,汤用中火炖了5分钟,盐放了2勺...”。

  2. 选择下一个进程 (Pick Next Process):

    • 理论:由操作系统的调度器(Scheduler) 从就绪队列中选择一个最合适的进程来运行。

    • 比喻:餐厅经理查看任务板(运行队列),根据优先级规则,决定接下来让哪位厨师(进程)进入厨房。

  3. 恢复上下文 (Restore the Context):

    • 理论:将下一个要运行进程的上下文信息,从其内核栈中加载到CPU的各个寄存器中。

    • 比喻:厨师B进入厨房。他并不关心上一位厨师做了什么。他拿出自己的记事本,按照上面的记录恢复工作现场:“哦,我上次鱼煎到一半,油温是七成热,下一步该翻面了...”。

  4. 跳转执行 (Jump and Execute):

    • 理论:将程序计数器(PC)设置为新进程的下一条指令地址,CPU开始执行新进程的代码。

    • 比喻:厨师B看了一眼记事本上记录的下一步骤,然后开始继续操作。

Linux O(1) 调度器😍

理论核心架构😜

运行队列 (Runqueue):

  • 理论:Linux为每个CPU核心都维护一个struct runqueue(运行队列)结构。这是调度的核心数据结构。

  • 比喻:这家餐厅的每个厨房(CPU核心) 都有自己独立的任务管理区(运行队列),这样多个厨房可以同时工作,互不干扰,避免了厨师们挤在一个任务板前争吵(避免了锁竞争)。

优先级数组 (Priority Arrays) - 活动队列与过期队列:

  • 理论:每个运行队列包含两个prio_array_t结构的数组:活动队列(active)过期队列(expired)

    • 活动队列 (active):存放所有时间片尚未耗尽的就绪进程。

    • 过期队列 (expired):存放所有时间片已经耗尽的就绪进程【新增进程/时间片到了的进程

  • 比喻:每个厨房的任务管理区都有两块巨大的白板

    • “正在叫号”板 (Active Board):上面挂着所有还有工作时间的厨师的订单。

    • “等待换班”板 (Expired Board):上面挂着所有工作时间已用完的厨师的订单。

队列结构 (Queue Structure):

  • 理论:每个prio_array_t包含:

    • queue[140]: 一个包含140个链表的数组。每个链表(queue[i])都是一个FIFO队列,存放着所有优先级为i的进程。下标即优先级,目前我们主要了解O(1)调度算法如何管理调度下标为【100-139】的普通进程【0-99】的实时进程的管理调度后面再继续了解~

    • bitmap[5]: 一个5*32=160位的位图(bitmap),每一位代表一个优先级队列是否为空(1为非空,0为空)。用于快速查找最高优先级的非空队列。

  • 比喻

    • “正在叫号”白板上有140个挂钩(queue[140],编号从0到139。编号越小,代表优先级越高(VIP挂钩)。

    • 每个挂钩上可以挂一串订单(进程链表),同一挂钩上的订单优先级相同,按先来后到的顺序排队。

    • 经理手边还有一个电子指示屏(bitmap,上面有140个小灯,每个灯对应一个挂钩。如果某个挂钩上有订单,对应的灯就会亮起。经理一眼扫过屏幕,就能立刻知道哪个编号最小的亮灯挂钩(即最高优先级的非空队列)。

更加形象可以看看下面这张图片:

调度过程 😜

  • 理论步骤

    1. 调度器查看active->bitmap,找到第一个被设置的位(即优先级最高的非空队列)。

    2. active->queue[i]中取出第一个进程。

    3. 将该进程投入运行。

    4. 当该进程的时间片用完,它会被从CPU上剥离。

    5. 调度器重新计算它的时间片和新优先级(可能根据其行为交互式还是计算型进行动态调整),然后将其放入expired->queue[k]中(k是计算出的新优先级)。

    6. 重复步骤1-5,直到active队列为空。

  • 比喻步骤

    1. 经理查看电子指示屏,找到编号最小的、灯还亮着的挂钩(比如101号)。

    2. 他走到101号挂钩前,取下最前面的那个订单,叫对应的厨师(比如厨师A)进厨房工作。

    3. 厨师A在厨房工作,直到经理喊“时间到!”。

    4. 厨师A出来,经理根据他刚才的表现(是一直在切菜(CPU密集型)还是经常等送食材(I/O密集型)),重新评估他的效率,并给他分配新的下次工作时间(重置时间片)。

    5. 然后经理把厨师A的订单挂到 “等待换班”板 的对应优先级的挂钩上(比如新优先级变成了105)。

    6. 经理继续从“正在叫号”板叫下一个厨师。

队列交换 🙃

  • 理论:当active队列完全为空时,调度器只需执行一个简单的指针交换操作swap(active, expired)。之后,原来的过期队列变成新的活动队列,而空的活动队列则成为新的过期队列

  • 比喻:当 “正在叫号”板 上的所有订单都被处理完,变得空空如也时。经理并不慌张,他做了一件非常聪明的事:直接把“正在叫号”和“等待换班”两块白板的标签互换!瞬间,满是订单的“等待换班”板变成了新的“正在叫号”板,而空的板子则成为了新的“等待换班”板。所有等待的厨师又都有了新的工作时间。

为什么叫O(1)算法?👌

  • 理论:无论系统中有多少进程,查找下一个要运行的进程的时间都是一个常数。因为它不遍历所有进程,而是通过查询固定大小的bitmap(常数时间)操作固定数量的队列(140个)来完成。

  • 比喻:无论餐厅有多少等待的厨师,经理决定下一个叫谁的时间都是一样的。他只需要看一眼固定大小的电子指示屏,而不是从头到尾数一遍所有厨师。

总结🐷

了解了这么多,我们可以看到Linux调度器的设计之美:

  • 效率:通过bitmap和双队列结构,将调度算法复杂度降为O(1)。

  • 公平:通过时间片轮转和优先级结合,保证所有进程都能得到执行,不会出现“饥饿”现象。

  • 智能:调度器会根据进程的过去行为(I/O密集还是CPU密集)动态调整其优先级,让交互式程序(如桌面点击)响应更快,体验更好。


♥♥♥本篇博客内容结束,期待与各位优秀程序员交流,有什么问题请私信♥♥♥

♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥

✨✨✨✨✨✨个人主页✨✨✨✨✨✨


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

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

相关文章

量子-resistant密码学研究

当亚马逊CloudFront在2025年9月宣布为所有TLS连接默认启用后量子加密支持时,这一举措标志着抗量子密码学从学术研究正式迈入大规模实用部署阶段。与此同时,密码学家们发出警告:一台拥有不到一百万噪声量子比特的计算机,可能在一周…

ARM 架构的存储器模型

ARM 架构的存储器模型 ARM 的存储器模型是一个相对复杂但设计精密的体系,它定义了处理器如何与内存进行交互,包括内存访问的顺序、可见性以及缓存行为等。这对于理解多核编程、并发控制和底层系统性能至关重要。 ARM 架构,特别是 ARMv8 及以后…

机器学习-多层感知机MLP

线性方法->多层感知机(MLP) 一个全连接(线性、dense)层有参数W∈Rm∗nW\in\R^{m*n}W∈Rm∗n,b∈Rmb\in\R^mb∈Rm,其用于计算输出yWxb∈RmyWxb\in\R^myWxb∈Rm 线性回归:全连接层有1个输出softmax 回归&a…

PostgreSQL——并行查询

这里写目录标题一、并行查询相关自己置参数二、并行扫描2.1、并行顺序扫描2.2、并行索引扫描2.3、并行index-only扫描2.4、并行bitmap heap扫描三、并行聚合四、多表关联4.1、Nested loop多表关联4.2、Merge join多表关联4.3、Hash join多表关联了解 Oracle 的朋友应该知道 Ora…

智能体赋能金融多模态报告自动化生成:技术原理与实现流程全解析

在金融领域,研报作为决策参考的核心载体,其生成过程往往涉及海量数据采集、多维度分析及专业内容整合,传统人工制作模式不仅耗时耗力,还难以满足实时性与标准化需求。随着人工智能技术的发展,“智能体赋能的金融多模态…

uniapp和vue3项目中引入echarts 、lime-echart(微信小程序、H5等)

目录标题1、获取 lime-echart插件2、安装 echarts3、相关代码4、在线定制5、效果截图1、获取 lime-echart插件 https://gitee.com/liangei/lime-echart 将其中组件和静态资源分别放入当前项目对应的文件夹中: 2、安装 echarts npm install echarts --save具体查…

ZYNQ7020+AD9361裸机驱动验证

1. 程序编译验证 a. 下载源代码 首先需要从GitHub下载相应的源码,打开git bash,然后在mingwin中使用以下命令下载源码。 git clone --recursive https://github.com/MicroPhase/antsdr_standalone.git 注意:在下载源码的时候,使…

Grafana配置连接时候证书与mongosqld启动证书的关系

目录 证书角色说明 1. BI Connector 端的证书 (--sslPEMKeyFile) 2. Grafana 端的证书 (TLS/SSL Client Certificate & Key) 它们之间的关系 配置建议 情况一:只需要服务器验证(最常见) 情况二:需要双向SSL认证&#x…

解决HTML/JS开发中的常见问题与实用资源

在前端开发过程中,即使是经验丰富的开发者也会遇到各种小问题。本文将聚焦于两个常见问题的解决方案,并推荐一些国内可访问的优质源码学习网站,帮助开发者提升效率。 一、字符编码与乱码问题解决 在HTML和JavaScript开发中,字符编…

SQLI-labs[Part 2]

本篇为SQLI-labs的Write-Up的第二部分包含Level 23- Level 27Level 23 过滤注释符 字符注入拼接语句发现注释符没有生效 应该是被过滤了那只能通过拼接语句来除去后面的影响拼接?id1 or 11?id1%27%20or%20%271%27%271源码中最后的导致语句闭合 Level 24 字符二次注入成功登录…

宋红康 JVM 笔记 Day17|垃圾回收器

一、今日视频区间 P169-P203 二、一句话总结 GC分类与性能指标;不同的垃圾回收器概述;Serial回收器:串行回收;ParNew回收器:并行回收;Parallel回收器:吞吐量优先;CMS回收器&#xff…

[硬件电路-194]:NPN三极管、MOS-N, IGBT比较

NPN三极管、MOS-N(N沟道MOS管)和IGBT(绝缘栅双极型晶体管)在电子电路设计中各有其独特的应用场景和优势,以下从工作原理、特性、应用领域三个维度进行比较:工作原理NPN三极管:结构:由…

【代码随想录day 25】 力扣 46. 全排列

视频讲解:https://www.bilibili.com/video/BV19v4y1S79W/?vd_sourcea935eaede74a204ec74fd041b917810c 文档讲解:https://programmercarl.com/0046.%E5%85%A8%E6%8E%92%E5%88%97.html#%E6%80%9D%E8%B7%AF 力扣题目:https://leetcode.cn/prob…

指针(五)后半

1、 qsort 函数1.1、qsort 函数排列结构体在这里&#xff0c;我们创建结构体类型的数组&#xff0c;用于 qsort 函数的传参。#include<stdio.h> #include<stdlib.h> #include<string.h>struct Stu//创建结构体变量 {char name[30];int age; };struct Stu arr…

TDengine 特殊选择函数 MODE() 用户手册

MODE 函数用户手册 函数定义 MODE(expr)功能说明 MODE() 函数返回指定列中出现频率最高的值&#xff08;众数&#xff09;。如果有多个值具有相同的最高频率&#xff0c;系统会返回其中一个值。该函数会忽略 NULL 值。 算法原理 MODE 函数的计算过程如下&#xff1a; 数据…

智能外骨骼技术应用场景及价格可接受区间分析

一、引言 智能外骨骼机器人融合机械、人工智能和传感器技术,增强或恢复人体运动能力。2025年,该技术在医疗康复、工业生产、军事应用和消费市场快速普及。本文分析其应用场景、市场需求、典型产品、价格可接受区间及相关来源,探讨普及的关键因素。 二、主要应用场景及产品…

Vue模板中传递对象或数组时,避免直接使用字面量[]和{}

在 Vue 中&#xff0c;直接在模板中使用 [] 或 {} 作为 prop 值会导致子组件不必要的重新渲染&#xff0c;因为每次父组件渲染时都会创建新的引用。以下是解决方案和最佳实践&#xff1a; 1. 避免在模板中直接使用字面量 <!-- 避免这样写 --> <ChildComponent :items&…

【C++】list容器的模拟实现

目录 1. 节点(list_node) 的结构 2. 哨兵位头节点 3. list容器的成员变量 4. 插入/删除操作 4.1 插入操作&#xff08;insert&#xff09; 4.2 删除操作&#xff08;erase&#xff09; 5. 迭代器的实现 6. 不同迭代器和const容器的限制 7. 重载operator-> 8. 迭代器…

三大运营商eSIM手机业务开通加速

截至2025年9月11日&#xff0c;中国三大运营商eSIM手机业务开通情况呈现明显差异化&#xff1a;中国联通已率先支持eSIM手机业务&#xff0c;但仅限于特定城市和设备&#xff1b;中国移动和中国电信则处于"技术准备就绪&#xff0c;等待政策批复"阶段&#xff0c;预计…

基于SpringBoot的足球论坛系统+论文示例参考

1.项目介绍 系统角色&#xff1a;管理员、普通用户功能模块&#xff1a;用户管理、足球赛事、球员信息、推荐话题、帖子信息、周边商城、订单信息、系统管理等技术选型&#xff1a;SpringBoot&#xff0c;Vue等 测试环境&#xff1a;idea2024&#xff0c;jdk1.8&#xff0c;mys…