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

进程优先级和切换

第一部分:进程优先级 (Process Priority)

系统中的进程成百上千,但 CPU(核)可能只有几个。谁先用 CPU?这就涉及到竞争性。为了合理分配资源,必须要有优先级 。

1. PRI 与 NI:一对“相爱相杀”的数值

在 Linux 中,衡量进程优先级的指标主要有两个:PRI(Priority) 和NI(Nice)。

  • PRI (Priority)
    • 含义:这是进程真正的优先级。值越小,优先级越高(越早被执行)。
    • 现状:用户通常无法直接硬性修改这个值,它由内核动态调整。
  • NI (Nice)
    • 含义:这个名字很有趣,意为“这个进程有多‘友善’”。
    • 作用:它是优先级的修正数据
    • 取值范围-2019,共 40 个级别 。
      • 负值(如 -20):表示“我不友善”,我要抢 CPU ->优先级变高
      • 正值(如 19):表示“我很谦让”,CPU 给别人先用 ->优先级变低
2. 计算公式

内核计算最终优先级的公式非常简单:

  • 结论:调整进程优先级,在 Linux 下,本质上就是调整nice 值
    • nice为负值,PRI变小,优先级变高。
    • nice为正值,PRI变大,优先级变低。

查看命令:

输入 ps -l 可以看到:

  • UID:谁启动的。
  • PRI:最终优先级。
  • NI:nice 值。

第二部分:进程切换 (Context Switch)

既然进程有优先级,高优先级的来了,正在跑的低优先级进程就得让路。或者时间片到了,大家轮流坐庄。

问题是:进程 A 被切下去时,它跑到哪一行代码、寄存器里存的临时结果怎么办?

这就涉及到了上下文 (Context)

1. 什么是“上下文”?

CPU 内有一堆寄存器(eax,ebx,eip程序计数器,esp栈指针等)。

  • 硬件层面:CPU 里的寄存器只有一套(物理硬件)。
  • 软件层面:每个进程都认为自己独占这些寄存器。

进程的上下文:就是进程执行时,CPU 寄存器中所有的临时数据8。

2. 切换过程

当 OS 决定把进程 A 换下,把进程 B 换上时,会发生以下动作:

  1. 保存 (Save):把 CPU 寄存器里属于进程 A 的数据,统统打包保存到进程 A 的PCB (task_struct)中(具体是保存在内核栈或 TSS 结构里)。
  2. 恢复 (Restore):从进程 B 的 PCB 中,把它上次没跑完的寄存器数据读出来,填回 CPU 的寄存器里 。
  3. 执行:CPU 指针 (eip) 指向了进程 B 上次停下的地方,继续运行。

课件中的比喻:

就像你读书记笔记。你要去吃饭(被切走),必须把书签夹好(保存上下文)。等你回来(被调度回来),翻到书签页(恢复上下文),继续往下读,而不是从头读 11。


第三部分:Linux 内核的 O(1) 调度算法

问题:如果有 1000 个进程,OS 怎么快速找到优先级最高的那个去运行?如果遍历链表,时间复杂度是 O(N),进程越多越慢。

Linux 2.6 引入了 O(1) 调度算法,不管有多少进程,查找时间都是固定的常数!

1. 核心数据结构:runqueue(运行队列)

每个 CPU 都有一个运行队列。在这个队列里,有两个关键的指针数组结构:活动队列 (Active)过期队列 (Expired)

结构如下(prio_array):

  • queue[140]:这是一个数组,包含了 140 个链表。
    • 优先级映射:第 0-99 号下标对应实时进程(我们暂不关心),100-139 号下标对应普通进程的优先级
    • 哈希桶原理:优先级为 100 的进程全挂在queue[100]的链表上,优先级 101 的挂在queue[101]上。
  • bitmap[5]:位图。用来标记哪个优先级的链表不为空。查找非空队列时,不需要遍历数组,直接查位图,效率极高 。
2. 运作机制
  1. 调度谁?

调度器直接去 活动队列 (Active) 里找优先级最高的(下标最小的)非空链表,拿出第一个进程去跑。因为有位图,这个过程是 O(1) 的 。

  1. 时间片用完了怎么办?

当一个进程时间片耗尽,它会被从 Active 队列 拿下来,重新计算优先级,然后扔到 Expired 队列 里去 。

  1. 乾坤大挪移 (关键!)

随着时间推移,Active 队列里的进程越来越少(都跑完去 Expired 了),Expired 队列里的进程越来越多。

当 Active 队列空了怎么办?

OS 只需要交换两个指针:activeexpired指针互换!

    • 原来的 Expired 瞬间变成了 Active,里面装满了分配好新时间片的进程。
    • 原来的 Active 变成了空荡荡的 Expired,准备接收下一波跑累的进程。
总结
  • 优先级 (PRI/NI)决定了进程在queue[140]数组中的位置。
  • 上下文切换保证了进程可以暂停和恢复。
  • O(1) 调度器利用双队列 (Active/Expired)指针交换,保证了在海量进程下系统依然极其流畅。
http://www.cnnetsun.cn/news/69895.html

相关文章:

  • [CISCN2019 华东南赛区]Web4
  • AI编程革命!Claude Skills大揭秘:小白也能快速上手的Agent开发神器,大模型开发者必看!
  • 内点法求最优潮流附matlab代码
  • 三相PWM整流器有限集模型预测电流控制附Simulink仿真模型
  • 光伏四可“可观”功能:光伏电站全景数字化的底层支撑技术
  • 如何用FLUX.1-dev镜像在本地部署下一代AI绘画模型?
  • 基于 Comsol 移动网格方法的激光熔池流动数值模拟
  • BLDC无刷直流电机Matlab仿真:转速电流双闭环控制及有感无感换相方式研究
  • [光学原理与应用-491]:水冷机、零气模块CDA、功率计等影响266皮秒紫外激光器的种子源1064nm功率稳定性结果的主要因素有哪些?
  • 昆仑通态MCGS与欧姆龙E5CC温控器通讯实战:PID模式及输出启停控制
  • 通达信〖逆势突破强牛〗指标公式 逆市环境中率先突破前期重要压力位 较强内在上涨动力
  • 基于扰动观测器的永磁同步电机(PMSM)模型预测控制(MPC)仿真探索
  • AEB联合仿真算法设计:Carsim2019.0+Matlab/Simulink2021a实现...
  • Java毕设选题推荐:基于springboot个人博客系统的设计与实现基于SpringBoot+Vue个人博客系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Java毕设选题推荐:基于springboot停车场车位预约系统基于Java springboot停车场管理系统停车位预约【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Java毕设选题推荐:基于springboot的无人化、线上化、数据化海洋馆预约系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Ascend C高级API应用:InitGlobalMemory与Pad操作的底层原理
  • Java毕设选题推荐:基于Java Web的新能源汽车信息咨询服务基于SpringBoot+Vue的新能源汽车信息咨询服务的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:OPA 集成指南:从原理到实践
  • Object.defineProperty和Proxy实现拦截的区别
  • 若依物联网
  • PSEN1抗体:如何揭示阿尔茨海默病致病机制与治疗新靶点?
  • Docker Engine 升级指南:保障容器安全的关键步骤
  • 基于zigbee灯光控制照明及色温调节系统的设计与实现(有完整资料)
  • 7、Python高级语法:描述器、属性与元编程实战
  • 【开题答辩全过程】以 基于java技术的校园一卡通系统的设计与实现为例,包含答辩的问题和答案
  • 11、Python 包与应用开发全解析
  • django基于智能推荐算法的全屋定制平台网站设计
  • 详谈:解释器模式(四)
  • 双Buck电路并联下的下垂控制与VDCM协同控制策略:增强直流微电网稳定性的仿真应用