Linux笔记---进程:进程切换与O(1)调度算法

1. 补充概念

1.1 并行与并发

  • 竞争性:系统进程数目众多,而CPU资源只有少量,甚至只有1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
  • 独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰。
  • 并行:多个进程在多个CPU下分别,同时进行运行,这称之为并行。
  • 并发:多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

由于在一个操作系统中进程的数量通常是很多的,所以并发的调度方式必不可少,在这篇文章中,我们要详细探讨进程是如何切换的。

1.2 实时操作系统与分时操作系统

  • 实时操作系统:是指系统能够及时响应外部事件的请求,在规定的时间范围完成对该事件的处理,并控制实时任务协调一致地运行。实时操作系统分为硬实时系统(如火箭和导弹控制)和软实时系统(如银行),需要具备实时时钟管理、过载防护和高可靠性等能力。
  • 分时操作系统:是一种允许多个用户同时共享一台计算机资源的操作系统。它通过将计算机的处理能力划分为多个时间片,轮流分配给不同的用户进程,使得每个用户都能在短时间内得到系统的响应,就好像独占使用整个系统一样。
  • 时间片:当代计算机都是分时操作系统,每个进程都有它合适的时间片(其实就是一个计数器)。时间片到达,进程就被操作系统从CPU中剥离下来,接着其他进程将占据CPU资源,该进程回到运行队列重新排队。

 进程的时间片用完就被CPU换下,让其他进程抢占CPU资源,这一点很好理解,但有两个问题:

  1. 当一个程序再次获得CPU资源时,如何接着上次运行的进度来继续运行?
  2. CPU是如何由优先级来决定谁该抢占CPU资源的?或者说优先级是如何实现的?

2. CPU上下文切换

在Linux操作系统中,CPU上下文切换是指在多任务处理时,CPU从一个任务切换到另一个任务的过程。这个过程包括保存当前任务的CPU寄存器和程序计数器的值,加载新任务的上下文到这些寄存器和程序计数器,然后跳转到程序计数器所指的新位置,开始运行新任务。

上下文切换的目的是为了让多个任务看起来像是同时运行,而实际上CPU在短时间内轮流执行这些任务。 

简单来说,每个进程在被换下时,会将当前CPU中寄存器的内容(上下文数据)保存到自己的PCB中维护起来,再将即将执行的进程的上下文数据加载到CPU中。

在task_struct中存在字段struct tss_struct tss,该结构体就用来保存进程的上下文数据。

struct tss_struct {
    struct x86_hw_tss x86_tss;
    unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
    unsigned long stack[64];
} ____cacheline_aligned;

struct x86_hw_tss {
    unsigned short back_link, __blh;
    unsigned long sp0;
    unsigned short ss0, __ss0h;
    unsigned long sp1;
    unsigned short ss1, __ss1h;
    unsigned long sp2;
    unsigned short ss2, __ss2h;
    unsigned long __cr3;
    unsigned long ip;
    unsigned long flags;
    unsigned long ax;
    unsigned long cx;
    unsigned long dx;
    unsigned long bx;
    unsigned long sp;
    unsigned long bp;
    unsigned long si;
    unsigned long di;
    unsigned short es, __esh;
    unsigned short cs, __csh;
    unsigned short ss, __ssh;
    unsigned short ds, __dsh;
    unsigned short fs, __fsh;
    unsigned short gs, __gsh;
    unsigned short ldt, __ldth;
    unsigned short trace;
    unsigned short io_bitmap_base;
} __attribute__((packed));
  1. x86_tss: 这是一个x86_hw_tss类型的结构体,它定义了硬件状态信息,包括寄存器的值、堆栈指针等。
  2. io_bitmap: 这是一个unsigned long类型的数组,用于存储I/O权限位图。
  3. stack: 这是一个unsigned long类型的数组,用于存储紧急内核堆栈。

上下文切换的性能影响

上下文切换是有一定开销的,每次上下文切换都需要几十纳秒到数微秒的CPU时间。特别是在进程上下文切换次数较多的情况下,很容易导致CPU将大量时间耗费在寄存器、内核栈以及虚拟内存等资源的保存和恢复上,进而大大缩短了真正运行进程的时间

3. O(1)调度算法

接下来的问题就是,操作系统如何根据优先级决定下一个接手CPU资源的进程是哪一个。

加入依次检查调度队列中的进程的优先级并从中选择的话,时间复杂度会达到O(n)。

O(1)调度算法是Linux内核中的一种进程调度算法,其名称中的“O(1)”表示该算法的时间复杂度是常数级别的,与系统中的进程数量无关。这种算法的设计目的是为了解决O(n)调度算法在处理大量进程时效率低下的问题。

下图是Linux中运行队列的结构示意图:

 我们要讨论的核心在于:

3.1 prio_array结构体

在runqueue中有一个只含两个元素的结构体数组字段,即图中的array[0]和array[1]:

struct prio_array {
    unsigned int nr_active; /* 本组中待处理进程的总数 */
    unsigned long bitmap[BITMAP_SIZE]; /* 用位图的方式表示某个优先级上有没有待处理的进程队列 */
    struct list_head queue[MAX_PRIO]; /* 与bitmap对应,存储所有待运行的进程 */
};

// #define 5 BITMAP_SIZE
// #define 140 MAX_PRIO
  1. nr_active:表示本组中待处理进程的总数。
  2. bitmap:这是一个位图,用于表示某个优先级上是否有待处理的进程队列。位图中的每一位对应一个优先级,1表示该优先级上有待处理的进程队列,0表示没有。
  3. queue:这是一个队列数组,用于存储所有待运行的进程。数组的下标对应进程的优先级,每个元素都是一个队列,队列中的节点是具有相同优先级的进程。例如,优先级为124的进程会被放到下标为124的队列中排队。

 根据上面的信息可以知道,整个操作系统中的优先级范围为[0,140),共140种:

  • 普通优先级:100〜139(对应nice值可取的40种优先级)。
  • 实时优先级:0〜99(不关心)。

通过让不同优先级的进程到不同的队列中排队,并按下标从低到高地调度每个队列,就保证了优先级高的进程先被执行。

bitmap是一个位图,包含5个整形元素,共160个比特位,前140个比特位依次对应140个优先级的队列 。通过这个bitmap就可以快速定位到非空的队列,而不用依次查找每个队列。

效率以及优先级如何保证的问题解决了,但是,被调度过后需要重新排队的进程以及新加入的进程应该被添加到哪里呢?假设重新添加到当前的queue中,那么在优先级高的进程被完全执行完毕之前,优先级较低的进程都不会被执行。

为了解决这个问题,我们提出了活跃队列和过期队列的概念。

3.2 活跃队列与过期队列

O(1)调度算法通过维护两个运行队列来实现:活动队列(active queue)和过期队列(expired queue)。活动队列中的进程是有资格获取CPU时间片的进程,而过期队列中的进程是已经用完时间片的进程。操作系统始终只会调度活动队列中的进程。

活动队列中的进程的时间片被用完之后会被添加到过期队列中,重新排队的同时,防止其一直占用CPU资源。

array[0]和array[1]轮流成为活动队列和过期队列,当活动队列中所有的进程都用完时间片,也就是活动队列中没有可运行的进程时,活动队列和过期队列进行交换。此时原来的过期队列变为活动队列,而原来的活动队列变为过期队列,新的活动队列中的进程又可以开始竞争CPU资源。

谁是活动队列,谁是过期队列,取决于active指针和expired指针的指向。

3.3 O(1)调度算法的优点

  • 高效性:由于查找下一个要运行的进程的时间复杂度为O(1),无论系统中有多少个进程都能快速地做出调度决策,提高了系统的响应速度和整体性能。
  • 公平性:保证了分时操作系统调度进程的公平性,每个进程都有机会运行。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言:深入理解指针

一.内存和地址 我们知道计算机上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们买电脑的时候,电脑上内存是 8GB/16GB/32GB 等,那这些内存空间…

mybatis学习(一)

声明:该内容来源于动力节点,本人在学习mybatis过程中参考该内容,并自己做了部分笔记,但个人觉得本人做的笔记不如动力节点做的好,故使用动力节点的笔记作为后续mybatis的复习。 一、MyBatis概述 1.1 框架 在文献中看…

【C++】list模拟实现(详解)

本篇来详细说一下list的模拟实现,list的大体框架实现会比较简单,难的是list的iterator的实现。我们模拟实现的是带哨兵位头结点的list。 1.准备工作 为了不和C库里面的list冲突,我们在实现的时候用命名空间隔开。 //list.h #pragma once #…

IT服务团队建设与管理

在 IT 服务团队中,需要明确各种角色。例如系统管理员负责服务器和网络设备的维护与管理;软件工程师专注于软件的开发、测试和维护;运维工程师则保障系统的稳定运行,包括监控、故障排除等。通过清晰地定义每个角色的职责&#xff0…

初学 flutter 问题记录

windows搭建flutter运行环境 一、运行 flutter doctor遇到的问题 Xcmdline-tools component is missingRun path/to/sdkmanager --install "cmdline-tools;latest"See https://developer.android.com/studio/command-line for more details.1)cmdline-to…

神经网络(系统性学习二):单层神经网络(感知机)

此前篇章: 神经网络中常用的激活函数 神经网络(系统性学习一):入门篇 单层神经网络(又叫感知机) 单层网络是最简单的全连接神经网络,它仅有输入层和输出层,没有隐藏层。即&#x…

H.265流媒体播放器EasyPlayer.js播放器提示MSE不支持H.265解码可能的原因

随着人工智能和机器学习技术的应用,流媒体播放器将变得更加智能,能够根据用户行为和偏好提供个性化的内容推荐。总体而言,流媒体播放器的未来发展将更加注重技术创新和用户互动,以适应不断变化的市场需求和技术进步。 提示MSE不支…

MySQL原理简介—6.简单的生产优化案例

大纲 1.MySQL日志的顺序写和数据文件的随机读指标 2.Linux存储系统软件层原理及IO调度优化原理 3.数据库服务器使用的RAID存储架构介绍 4.数据库Too many connections故障定位 1.MySQL日志的顺序写和数据文件的随机读指标 (1)磁盘随机读操作 (2)磁盘顺序写操作 (1)磁盘随…

svn 崩溃、 cleanup失败 怎么办

在使用svn的过程中,可能出现整个svn崩溃, 例如cleanup 失败的情况,类似于 这时可以下载本贴资源文件并解压。 或者直接访问网站 SQLite Download Page 进行下载 解压后得到 sqlite3.exe 放到发生问题的svn根目录的.svn路径下 右键呼出pow…

前后端分离,解决vue+axios跨域和proxyTable不生效等问题

看到我这篇文章前可能你以前看过很多类似的文章。至少我是这样的,因为一直没有很好的解决问题。 正文 当我们通过webstorm等IDE开发工具启动项目的时候,通过命令控制台可以观察到启动项目的命令 如下: webpack-dev-server --inline --prog…

在win10环境部署opengauss数据库(包含各种可能遇到的问题解决)

适用于windows环境下通过docker desktop实现opengauss部署,请审题。 文章目录 前言一、部署适合deskdocker的环境二、安装opengauss数据库1.配置docker镜像源2.拉取镜像源 总结 前言 注意事项:后面docker拉取镜像源最好电脑有科学上网工具如果没有科学上…

Java开发经验——Spring Test 常见错误

摘要 本文详细介绍了Java开发中Spring Test的常见错误和解决方案。文章首先概述了Spring中进行单元测试的多种方法,包括使用JUnit和Spring Boot Test进行集成测试,以及Mockito进行单元测试。接着,文章分析了Spring资源文件扫描不到的问题&am…

2024年亚太地区数学建模大赛D题-探索量子加速人工智能的前沿领域

量子计算在解决复杂问题和处理大规模数据集方面具有巨大的潜力,远远超过了经典计算机的能力。当与人工智能(AI)集成时,量子计算可以带来革命性的突破。它的并行处理能力能够在更短的时间内解决更复杂的问题,这对优化和…

基于 RBF 神经网络整定的 PID 控制

基于 RBF 神经网络整定的 PID 控制 是结合了传统 PID 控制和 RBF(径向基函数)神经网络的自适应控制方法。在这种方法中,RBF 神经网络用于自适应地调整 PID 控制器的增益(比例增益 KpK_pKp​,积分增益 KiK_iKi​ 和微分…

空间注意力网络的性能优化与多维评估

在本文中,首先分析空间注意力网络(Spatial Attention Neural Network)在五个不同数据集上的训练结果。这些数据集包括Daily_and_Sports_Activities、WISDM、UCI-HAR、PAMAP2和OPPORTUNITY。通过对比这些结果,我们可以深入理解空间…

Linux——1_系统的延迟任务及定时任务

系统的延迟任务及定时任务 在系统中我们的维护工作大多数时在服务器行对闲置时进行 我们需要用延迟任务来解决自动进行的一次性的维护 延迟任务时一次性的,不会重复执行 当延迟任务产生输出后,这些输出会以邮件的形式发送给延迟任务发起者 在RHEL9中…

【数据结构】—— 线索二叉树

引入 我们现在提倡节约型杜会, 一切都应该节约为本。对待我们的程序当然也不例外,能不浪费的时间或空间,都应该考虑节省。我们再观察团下图的二叉树(链式存储结构),会发现指针域并不是都充分的利用了,有许…

NVR管理平台EasyNVR多个NVR同时管理:全方位安防监控视频融合云平台方案

EasyNVR是基于端-边-云一体化架构的安防监控视频融合云平台,具有简单轻量的部署方式与多样的功能,支持多种协议(如GB28181、RTSP、Onvif、RTMP)和设备类型(IPC、NVR等),提供视频直播、录像、回放…

虚幻引擎---初识篇

一、学习途径 虚幻引擎官方文档:https://dev.epicgames.com/documentation/zh-cn/unreal-engine/unreal-engine-5-5-documentation虚幻引擎在线学习平台:https://dev.epicgames.com/community/unreal-engine/learning哔哩哔哩:https://www.b…

汽车HiL测试:利用TS-GNSS模拟器掌握硬件性能的仿真艺术

一、汽车HiL测试的概念 硬件在环(Hardware-in-the-Loop,简称HiL)仿真测试,是模型基于设计(Model-Based Design,简称MBD)验证流程中的一个关键环节。该步骤至关重要,因为它整合了实际…