[Linux] Linux 的进程如何调度——Linux的 O(1)进程调度算法
标题:[Linux] Linux 的进程如何调度——优先级与进程调度
个人主页@水墨不写bug
目录
一、前言
二、将要出现的概念
1.进程调度队列
2.位图
3.进程的优先级
三、Linux进程的调度过程
1.活动队列(*active指向的队列)
2.过期队列(*expired指向的队列)
3.active指针和expired指针
4.总结
正文开始:
一、前言
当你看过书上的讲解,它通常会将操作系统对进程的调度一笔带过:
一个一个的进程会被存储在队列中(称为运行队列),CPU通过运行队列来调度进程。
这样的讲解通常让人捉摸不透,Linux操作系统具体是怎么调用进程的?又是怎么一个调用法?能不能用直观的图来表示这样的调度过程?这就是本文着重讲解的内容。
二、将要出现的概念
1.进程调度队列
Linux中,每个CPU都对应有一个运行队列;CPU与运行队列是一对一的关系。CPU想要调度进程,就需要到runqueue这个数据结构中去得到进程的PCB:task_struct。
在这里,我们形象的表示出runqueue:
在runqueue中,由于不考虑其他的信息,只考虑进程调度相关的变量,我们仅仅在上面的图形中表示出了进程调度的关键信息。首先我们会发现,红色和蓝色分别是两组相同的结构,这与调度的逻辑密切相关。
这两组相同的结构,一组表示正在被调度的进程队列,另一组是未被调度的进程队列。这里的队列(queue)要与运行队列(runqueue)区分,这里的队列的实际类型是:
struct task_struct *queue[140];
运行队列是一个CPU调度对应的一个数据结构,但是这里的队列只是运行队列中的一个组织进程的数据结构。
2.位图
在C++中,位图(bitmap)通常指的是一种用于表示和操作位(bit)的数据结构。位图可以被看作是一个由连续的位(0或1)组成的序列,其中每一个位都可以表示某个状态或属性的值。
在C++中,可以使用位操作(bit manipulation)来对位图进行操作,例如设置某个位的值、获取某个位的值、将多个位进行逻辑运算等。常见的位操作操作符包括位与(&)、位或(|)、位异或(^)、位取反(~)等。
使用位图可以实现一些高效的算法和数据结构,例如位图可以被用来表示一个大范围的二进制数,节省内存空间。位图也可用于表示布尔值数组、位向量(bit vector)、位集合(bit set)等数据结构。
在我们上述的两个相同的结构中,都有一个位图bitmap[5]:
int bitmap[5];
int具有32位,可以表示32个状态值,5个int则可以表示160个状态值,正好可以覆盖140个大小的PCB数组。用位图表示PCB数组的这个位置上是否有进程。实际上PCB数组内存储的是一个task_struct*的链表,在具体调用时,如果这个位置上有链表,则取出头节点,加载到CPU中调度。
我们首先需要知道,Linux操作系统想要正常为用户服务,就需要不断的调度用户的进程,所以调度进程是一个每时每刻都在发生的事。想要调度进程,Linux就需要在进程队列中查找进程。运行队列是一个指针数组,每一个位置只可能有两种状态:
1)存储有有效的进程地址;
2)空指针;
这就需要一个非常高效的确认进程队列中每一个位置是否有进程的查找方法——这也就是在这里位图的用武之地:
我们可以通过访问表示位图数组的每一个元素,每一个元素是整形,表示32个位置是否有指针存在:这样我们就可以通过一次判断,就可以知道32个位置是否有进程了!!!
3.进程的优先级
在Linux操作系统中,优先级是相对于拥有时间片的进程而言的。进程分为实时进程和分时进程,分时进程才有时间片的概念,并会被根据优先级依次被操作系统调度。
上述的140个数组位置而言:
普通优先级: 100~ 139(我们创建的进程一般普通的优先级,想想nice值的取值范围,可与之对应!)
实时优先级: 0~ 99(在这里我们不关心)
除此之外,如果你优先级不太了解, 可参考 (《进程的优先级》)。
我们在之前的讲解中,我们明白了这样的一个事实:CPU是稀缺资源,相对于CPU的数目来说,进程的数目是更多的,进程的调度需要CPU,于是进程需要竞争CPU资源,这也就需要指定进程优先级。
进程的优先级与操作系统的尽量让每个进程调度的总时间是相同的原则是不冲突的,在本文的第三部分会有详尽的演示。
三、Linux进程的调度过程
1.活动队列(*active指向的队列)
时间片还没有结束的所有进程都按照优先级放在该队列;
nr_active: 表示总共有多少个运行状态的进程;
queue[140]: 一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进行排队调度,所以,数组下标就是优先级!
从该结构中,选择一个最合适的进程,过程是怎么的呢?
1. 从0下表开始遍历queue[140]
2. 找到第一个非空队列,该队列必定为优先级最高的队列
3. 拿到选中队列的第一个进程,开始运行,调度完成!
4. 遍历queue[140]时间复杂度是常数!但还是太低效了!
bitmap[5]:一共140个优先级,一共140个进程队列,为了提高查找非空队列的效率,就可以用5*32个比特位表示队列是否为空,这样,便可以大大提高查找效率
2.过期队列(*expired指向的队列)
过期队列和活动队列结构一模一样;
过期队列上放置的进程,都是时间片耗尽的进程;
当活动队列上的进程都被处理完毕之后,对过期队列的进程进行时间片重新计算;
3.active指针和expired指针
active指针永远指向活动队列
expired指针永远指向过期队列
可是活动队列上的进程会越来越少,过期队列上的进程会越来越多,因为进程时间片到期时一直都存在的。
为了解决这个问题,操作系统会在合适的时候交换两个指针的内容,这样就完成了操作系统对进程的调度的可持续进行。
由于查找进程的顺序是从小下标到大下标查找的,这也就导致了优先级数值比较小的进程会优先被调用,但是终究是要在这个进程队列调度完成之后才能进行下一轮进程进程调度,这就很好的体现了优先级的意义:优先级高,体现在每个调度周期中先调度这个优先级高的进程。
4.总结
在系统当中查找一个最合适调度的进程的时间复杂度是一个常数,不随着进程增多而导致时间成本增加,我们称之为进程调度O(1)算法。
完~
未经作者同意禁止转载
相关文章:

[Linux] Linux 的进程如何调度——Linux的 O(1)进程调度算法
标题:[Linux] Linux 的进程如何调度——优先级与进程调度 个人主页水墨不写bug 目录 一、前言 二、将要出现的概念 1.进程调度队列 2.位图 3.进程的优先级 三、Linux进程的调度过程 1.活动队列(*active指向的队列) 2.过期队列&#…...
Python使用Selenium动态爬取CSDN社区帖子的URL链接
前几天读了一篇CSDN社区的帖子,发现文章内容写得极好,值得借鉴学习。于是我想将那个社区的帖子都爬下来,但是那个社区发布的贴子挺多的,一直往下拉才到2022年5月的发布。于是我就只将5月份之前的爬下来就行,但是帖子是…...
【ShuQiHere】双系统指南:如何在 Linux 系统情况下安装 Windows 11,处理引导与网络问题 ️
【ShuQiHere】 🖥️💡 在安装 Windows 11 和 Linux 双系统时,常常会遇到各种棘手的问题,特别是在网络连接、BIOS 设置和引导修复方面。今天我将详细带你解决这些问题,让你顺利完成 Windows 11 安装,并恢复…...
jQuery EasyUI 扩展
jQuery EasyUI 扩展 引言 jQuery EasyUI 是一个流行的 HTML5 框架,用于构建交互式网页界面。它提供了一系列的 UI 组件,如布局、窗口、数据网格等,使得网页开发变得更加简单快捷。然而,尽管 EasyUI 功能丰富,但在某些特定场景下,开发者可能需要更多的定制化功能或组件。…...
408算法题leetcode--第24天
#378. 有序矩阵中第 K 小的元素 378. 有序矩阵中第 K 小的元素思路:值二分,如注释时间:O(log(r-l) * n);空间:O(1) class Solution { public:int check(vector<vector<int>>& matrix, int target){/…...

【CKA】二、节点管理-设置节点不可用
2、节点管理-设置节点不可用 1. 考题内容: 2. 答题思路: 先设置节点不可用,然后驱逐节点上的pod 这道题就两条命令,直接背熟就行。 也可以查看帮助 kubectl cordon -h kubectl drain -h 参数详情: –delete-empty…...
STM32中断编程指南:NVIC和中断优先级
在STM32微控制器编程中,中断是实现多任务处理和实时响应的关键技术。NVIC(Nested Vectored Interrupt Controller)是STM32中的中断控制器,负责管理中断请求、优先级和中断向量。本文将详细介绍STM32的NVIC配置和中断优先级设置&am…...

ThreadLocal底层原理及数据结构详解
ThreadLocal允许为每个线程创建独立的变量副本,使得同一个ThreadLocal对象在不同的线程中拥有不同的值。它的主要作用是在并发环境下提供线程隔离,避免多个线程共享同一个变量,从而减少线程间的相互干扰。 ThreadLocal的核心在于为每个线程维…...

Android Framework AMS(02)AMS启动及相关初始化5-8
该系列文章总纲链接:专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明: 说明:本章节主要涉及systemserver启动AMS及初始化AMS相关操作。同时由于该部分内容过多,因此拆成2个章节,本章节是第二章节&…...
速盾:游戏被攻击怎么办?
随着游戏行业的发展,游戏被攻击的情况也越来越多见。游戏被攻击可能导致游戏服务器崩溃、用户数据泄露、游戏体验受影响等问题。作为游戏开发者或运营商,面对游戏被攻击的情况,应该采取一系列的措施来应对。 首先,要及时发现游戏…...

BUU刷题-Pwn-shanghai2018_baby_arm(ARM_ROP_csu_init,ARM架构入门)
解题思路: 泄露或修改内存数据: 堆地址:无需栈地址:无需libc地址:无需BSS段地址:无需 劫持程序执行流程:ARM_ROP && mprotect函数(运行内存权限修改) && [[ARM_ROP_csu_init]…...

flutter_鸿蒙next(win)环境搭建
第一步 拉取鸿蒙版本flutterSDK仓库 仓库地址:OpenHarmony-SIG/flutter_flutter 第二步 找到拉取的仓库中的README.md 并根据说明配置环境 第三步 配置好环境变量之后 用管理员开启cmd 输入:flutter dcotor 并查看此时flutter所支持的系统 包括&…...

腾讯一面-LRU缓存
为了设计一个满足LRU(最近最少使用)缓存约束的数据结构,我们可以使用哈希表(HashMap)来存储键值对,以便在O(1)时间复杂度内访问任意键。同时,我们还需要一个双向链表(Doubly Linked …...

k8s实战-1
k8s实战-1 一、资源创建方式1.命令行2.yaml 二、命名空间三、Pod总结 一、资源创建方式 1.命令行 就是直接通过命令的方式创建,比如我要创建namespace, kubectl create namespace hello删除: kubectl delete -f hello2.yaml 简单来说&am…...
Python进程池:提升你的并发性能
引言 在现代编程中,多核处理器的普及使得并发编程变得尤为重要。Python,作为一种广泛使用的编程语言,提供了多种并发和并行编程的工具。其中,multiprocessing库中的进程池(Pool)是一个强大的工具ÿ…...

内存占用估算方法
优质博文:IT-BLOG-CN 通过掌握每种数据类型的大小,就可以更准确地预测对象和数据的内存消耗。 一、基础数据类型 Java基础数据类型结构,在64位系统开启指针压缩情况下的内存占用字节数: booleanbytecharshortintlongfloatdoub…...

拓扑排序简介
拓扑排序(Topological Sort)是一种重要的图算法,用于对有向无环图(DAG, Directed Acyclic Graph)中的节点进行排序。拓扑排序的结果是一种线性序列,使得对于图中的任意一条有向边(u, v),顶点u都在顶点v之前。这种排序常用于任务调度、编译器依赖关系分析等领域。 拓…...
使用iTextPDF库时,设置文字为中文格式
在使用iTextPDF库时,设置文字为中文格式主要涉及选择合适的中文字体,并确保该字体能够正确渲染中文字符。由于iTextPDF的内置字体通常不支持中文,因此你需要加载一个支持中文的字体文件(如TrueType字体,.ttf文件&#…...

Windows环境下使用Docker配置MySQL数据库
用Docker配置数据库,无论是做开发,还是做生产部署,都非常的方便 它不需要单独安装数据库,也不用担心出现各种环境的配置问题。 本文将分享用Docker配置数据库的步骤,这里用MySQL举例。 其他的数据库如MSSQL…...

快速上手C语言【上】(非常详细!!!)
目录 1. 基本数据类型 2. 变量 2.1 定义格式 和 命名规范 2.2 格式化输入和输出(scanf 和 printf) 编辑 2.3 作用域和生命周期 3. 常量 4. 字符串转义字符注释 5. 操作符 5.1 双目操作符 5.1.1 算数操作符 5.1.2 移位操作符 5.1.3 位操作符…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...