【Linux】进程调度 | 进程切换上下文数据

🪐🪐🪐欢迎来到程序员餐厅💫💫💫

          主厨:邪王真眼

主厨的主页:Chef‘s blog  

所属专栏:青果大战linux

总有光环在陨落,总有新星在闪烁


小感慨:

ddl是这样的,老师只要布置作业就好了,我们学生要考虑的就多了

进程优先级

基本概念

  • cpu资源分配的先后顺序就是进程的优先级
  • 优先级高的进程优先被CPU执行。优先级低的进程会较后地被执行,合理的配置不同进程的优先级可以更好的满足用户的需求

查看进程优先级

linux或者unix系统中,用ps –l命令则会输出进程的相关信息,如下

  • UID : 代表执行者的身份

  • PID : 代表这个进程的代号

  • PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号

  • PRI :代表这个进程可被执行的优先级,其值越小越早被执行

  • NI :代表这个进程的nice值

在未修改状态下,PRI是一个进程的默认优先级大小,不同的进程初始PRI可能一样可能不一样,nice是对该默认值进行的修改大小,nice的范围是[-20,19],相当于优先级的大小范围是[60,99]共计40个种类。

为什么Linux会对nice的大小进行限制呢?这其实是怕用户乱设置优先级,比如直接来个10000或者-10000,这样就会难以管理,这点在后面的运行队列结构分析会讨论。


修改优先级

我们现在启动了一个进程(死循环),他的PID是8947
输入top指令进入该界面

输入r表示开始修改nice,接着他会弹出一条命令行,我们接着输入我们要修改的进程的PID

输入我们想要把nice修改成多少即可

最后输入q退出该界面,再输入ps -al查看进程,就会发现我们NI值变成了15,PRI值变成了95

但是请注意,我们的PRI结果=PRI的初始值+NI,而不是上一次的PRI+NI

我们现在试试把NI改为-15,就会发现他的值是65(初始值80-15),而不是80(上一次的值95-15)


进程调度

进程调度是指OS在管理进程的执行时所采取的策略

优先级管理

我们之前提到过,OS对进程的管理就是”先描述,再组织“,先把进程描述为task_struct,接着再维护称链表等数据结构。

接着我们思考两点

  • CPU是极其注重效率的,即时间复杂度要尽可能的去压缩,

  • CPU运行进程依靠的不是他的先来后到,而是优先级(其实也不止,但先考虑这么多)。

根据第一点,我们就想到要队列这种数据结构维护运行队列,可以达到O(1)的时间复杂度

根据第二点,我们想到堆的数据结构,达到考虑优先级的目的。

合二为一,怎么办?

于是伟大的哈希出现了,我们采用开散列(哈希桶)的方法,我们可以开一个40个元素的vector,里面放PCB指针。

假如有个这样在有新的进程要加入运行队列,他的优先级是60,我们就可以把它放到第一个元素所维护的链表中。

当CPU也只需要从头到尾遍历哈希表,即可实现按照优先级运行进程。

但是,假如只有一张哈希表,当优先级高的进程被弹出后(时间片限制),他还要重新接入哈希表(因为还没跑完),还会原来的那个位置,这就会导致后面的进程一直等待。所以我们发现一张哈希不够,要两张,一张放置运行队列,另一张放置从运行队列弹出但是还没运行完需要接着跑的进程。当运行队列跑完了,就直接交换两个队列的指针(O(1)),于是CPU就可以继续运行进程了。

代码演示

我们先写了一个结构体Queue,他的成员对象有三个

当num为0说明该队列的进程全被运行了一遍,可以更换哈希表了

数组开了140个是因为OS会把前100个用于实时进程,关于实时进程我们目前不用考虑当不存在就ok。

接着我们写了一个结构体,它就是我们一直说的运行队列

active指向当前CPU要去运行的进程所组成的Queue对象

expired指向从运行队列弹出,要接着排队的进程所组成的Queue对象

现在我们假设CPU把它上面的一个进程A跑完了,于是他要去找下一个进程B,有个很简单的方法,他直接对这个140的数组遍历,遇到的第一个task_struct就是所存放的进程中优先级最高的进程。

于是直接把A和B交换,然后把A存放到expired里即可,这样的时间复杂度是O(1),但他最坏要循环140次

Linux社区里的大佬并不满意这种效率,于是位图闪亮登场,一共是140个元素,我们可以用5个int的比特位,来存储各个优先级对应位置的状态,如果第三个位置有进程插入,那第三个比特位就是1,否则是0,以此类推。于是我们可以这么写

加入从0开始的32个比特位都为0,则bitmap[0]=0,于是我们可以直接排查掉32个比特位,假如发现bitmap[i] 不为0,接着就通过lowbite的方法直接找到是最早哪个bite为不为0(自低位向高位查找)

于是时间复杂度直接提高到遍历个位数次即可。这就是linuxO(1)调度算法

当然,具体要更加复杂,因为我们的CPU是分时CPU,所以对于那些明明在运行队列呆了很久运行时间却很短的进程,OS会提高他的优先级,反之亦然,诸如此类的操作还有别的,但笔者能力有限还不了解。

当OS发现该num==0,即active所维护的哈希表空了,就让swap一下active指向arr[1],让expired指向arr[0],如此反复交换,就实现了OS的优先级管理

swap(active,expired);

PCB的双链表结构

从最开始接触进程开始我们就说了,OS会通过指针把PCB链接起来进行管理,但是它并不像我们学的简单的双链表结构如下

我们并没有把连接字段直接写进去,而是这样的:

 因为我们一个PCB可能既在一个键盘的等待队列,也在一个鼠标的等待队列,或是别的队列,如果是在建立一个PCB显然是有新的内存开销的,于是当一个进程需要带着多个队列中时,只需要向他的PCB中写入新的节点字段即可

但随之而来一个问题,我们得到这个节点字段的指针后如何访问她所在结构体PCB的其他成员呢?

如果得到的是这个进程PCB的指针那可以直接用”->“进行访问,但我们得到的不是该PCB的地址,而是他内部的某个成员的地址。这里就要用c语言中offset宏了。他的原理很简单。

结合这个代码演示大家就知道成员变量的地址和该结构体的地址是有关系的,我们只要求出他们之间的偏移量即可。这并不困难,使用下面的代码即可。

 于是我们就可以通过结构体的某个成员找到该结构体的地址了。


进程切换

我们知道了进程是如何进行优先级管理的了,但是现在我们去把目光放到单独的一次进程切换中。

  1. 进程A时间片到了,被移除,换进程B上来
  2. A等待一段时间后再次被调度

此时A进程当让应该接着被移除前的进度继续运行,可是,它怎么直到上次跑到哪了?

显然,这里出现了数据的读取和存储

进程在进行切换时会出现大量的临时数据需要保存,我们讲这些数据称之为进程的上下文数据

首先,这些数据不可能存在CPU,因为CPU太小了(几十KB),也不会存在磁盘,因为进程本身就是掉电就丢失,那在掉电后你在磁盘保存下来他的上下文数据也没有意义了,于是他的数据只会呆在内存,而且应该是和该进程紧密相关的一片空间,没错,就是task_struct!

我们可以抽出两个寄存器细说一下

 程序一开始,PC寄存器会把程序的第一条指令(main函数)地址读进去,接着ir会根据该地址找到指令内容,并将其读进去,然后交给处理器处理指令,与此同时PC寄存器会更新地址,具体为新地址=原地址+该地址对应指令长度,于是ir再次获取新指令,循环往复。

当进程第二次被加载进CPU时,ir就会读取task_struct中存储的上一次运行的最后一条指令的地址,而不是该程序的第一条指令地址,于是程序就可以继续跑了。


思维导图

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

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

相关文章

区块链系统控制台Console的安装与运维

【要求】 登陆Linux 服务器,安装、部署区块链系统控制台 Console,并完成节点的运维。同 时,检查控制台是否能够正常运行。 【任务】 1. 登陆 linux 服务器,进入指定操作目录按下列要求完成控制的安装与部 署,并将安装过…

Rust语言的优缺点以及学习建议

在编程世界的不断演变中,Rust 作为一种重要的语言脱颖而出。它以安全性和性能为核心,正在获得开发者们的广泛关注。但究竟什么是 Rust?它为何如此受欢迎?在这篇博客中,我们将深入探讨 Rust 的世界,探索它的…

【三十七】【QT开发应用】使用QVideoWidget播放视频,QT模块缺失时更新安装模块步骤(利用虚拟网址打开应用加速)

效果展示 下面有一个按钮打开视频&#xff0c;点击按钮之后会出现一个弹窗选择文件&#xff0c;默认打开的是D盘&#xff0c;并且选择的文件的类型有.mp4 .flv或者所有文件。选择正确的视频文件之后可以正常播放视频。 widget.h 主窗口头文件 #pragma once#include <QtWid…

【设计模式系列】适配器模式(九)

目录 一、什么是适配器模式 二、适配器模式的角色 三、适配器模式的典型应用 四、适配器模式在InputStreamReader中的应用 一、什么是适配器模式 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将不兼容的接口转换为一个客户端…

【Vue】word / excel / ppt / pdf / 视频(mp4,mov) 预览

文件预览 Vue3一. word二. excel三. ppt四. pdf4.1 vue-pdf-embed4.2 iframe 五. 视频六&#xff1a;扩展——kkFileView Vue3 一. word 安装&#xff1a;npm install docx-preview父页面 <template><div><DocPreviewv-if"filePath.includes(docx)"…

Cisco Packet Tracer 8.0 路由器单臂路由配置

文章目录 单臂路由简介一、单臂路由的原理二、单臂路由的配置步骤三、单臂路由的优缺点四、应用场景 一&#xff0c;拓扑图搭建二&#xff0c;pc IP地址配置三&#xff0c;交换机Switch0配置四&#xff0c;配置路由器Router0五&#xff0c;测试 单臂路由简介 单臂路由&#xf…

Hadoop-001-本地虚拟机环境搭建

一、安装VMware 官方下载VMware&#xff1a; https://vmware.mdsoft.top/?bd_vid5754305114651491003 二、下载镜像文件 阿里云镜像仓库&#xff1a; https://mirrors.aliyun.com/centos/ 本文档使用 CentOS-7-x86_64-DVD-1810-7.6.iso 搭建虚拟机 三、搭建虚拟机 1、编辑…

【WRF数据准备】基于GEE下载静态地理数据-叶面积指数LAI及绿色植被率Fpar

【WRF数据准备】基于GEE下载静态地理数据 准备:WRF所需静态地理数据(Static geographical data)数据范围说明基于GEE下载叶面积指数及绿色植被率GEE数据集介绍数据下载:LAI(叶面积指数)和Fpar(绿色植被率)数据处理:基于Python处理为单波段LAI数据参考GEE的介绍可参见另…

VantUI

官网&#xff1a;Vant 4 - A lightweight, customizable Vue UI library for mobile web apps. Vant组件库&#xff1a; 基础组件 按钮、图标、布局、提示信息等 表单组件 日历、复选框、时间选择、输入框、评分等 反馈组件 弹出框、加载、下拉菜单、消息提示、下拉刷新、滚动…

面试阿里、字节全都一面挂,被面试官说我的水平还不如应届生

测试员可以先在大厂镀金&#xff0c;以后去中小厂毫无压力&#xff0c;基本不会被卡&#xff0c;事实果真如此吗&#xff1f;但是在我身上却是给了我很大一巴掌... 所谓大厂镀金只是不卡简历而已&#xff0c;如果面试答得稀烂&#xff0c;人家根本不会要你。况且要不是大厂出来…

C#入坑JAVA MyBatis入门 CURD 批量 联表分页查询

本文&#xff0c;分享 MyBatis 各种常用操作&#xff0c;不限于链表查询、分页查询等等。 1. 分页查询 在 下文的 的「3.4 selectPage」小节&#xff0c;我们使用 MyBatis Plus 实现了分页查询。除了这种方式&#xff0c;我们也可以使用 XML 实现分页查询。 这里&#xff0c…

1-petalinux2018.3 摸索记录 -petalinux-config

一、petalinux-config的具体配置-ZYNQMP Configuration 1、Linux Compoment Selection Linux Compoment Selection&#xff0c;Linux组件选择. First Stage Bootloader和Auto update ps_init勾选会自动生成fsbl.elf&#xff0c;自动更新ps_init。 PMU Firmware平台管理单元固…

熵与信息论

经典信息论的核心概念是香农熵。假设我们得到了一个变量X的值&#xff0c;X的香农熵量化了我们在获悉 X的值时所能得到的平均信息量&#xff1b;另一种观点是将X的看作在我们获悉的值前对其不确定程度的度量。这两种观点是互补的&#xff1b;我们既可以将看作在我们获悉X的值前…

Ubuntu 22.04系统启动时自动运行ROS2节点

在 Ubuntu 启动时自动运行 ROS2 节点的方法 环境&#xff1a;Ubuntu 系统&#xff0c;ROS2 Humble&#xff0c;使用系统自带的 启动应用程序 目标&#xff1a;在系统启动时自动运行指定的 ROS2 节点 效果展示 系统启动后&#xff0c;自动运行小乌龟节点和键盘控制节点。 实践…

龙蟠科技业绩压力显著:资产负债率持续攀升,产能利用率也不乐观

《港湾商业观察》施子夫 黄懿 去年十月至今两度递表后&#xff0c;10月17日&#xff0c;江苏龙蟠科技股份有限公司(以下简称&#xff0c;龙蟠科技&#xff1b;603906.SH&#xff0c;02465.HK)通过港交所主板上市聆讯。 很快&#xff0c;龙蟠科技发布公告称&#xff0c;公司全…

OceanBase 安全体系解析之身份鉴别

本文作者&#xff1a;金长龙爱可生测试工程师&#xff0c;负责 DMP 产品的测试工作。 本文以MySQL为参照&#xff0c;详细阐述了OceanBase 在MySQL模式下的安全体系中&#xff0c;身份鉴别的能力&#xff0c;涵盖了身份鉴别机制、用户名的构成规则、密码的复杂度&#xff0c;以…

在Java中的动态绑定和静态绑定

动态绑定和静态绑定是两种方法调用的绑定机制静态绑定 静态绑定也称为早期绑定&#xff0c;是在编译时确定调用的方法。动态绑定 动态绑定也称为晚期绑定&#xff0c;是在运行时确定调用的方法。静态绑定用于编译时确定的方法调用&#xff0c;动态绑定是Java实现运行时多态的…

CISE|暴雨受邀出席第二十六届中国国际软件博览会

10月24日至26日&#xff0c;备受瞩目的第二十六届中国国际软件博览会&#xff08;简称CISE&#xff09;在国家会展中心&#xff08;天津&#xff09;圆满举办。CISE不仅汇聚了来自全国各地的顶尖软件企业和机构&#xff0c;还吸引了众多专家学者和行业精英共襄盛举&#xff0c;…

Cesium基础-(Entity)-(Box)

** 里边包含Vue、React框架代码详细步骤、以及代码详细解释 ** 3、Box 盒子 以下是 BoxGeometry 类的属性、方法和静态方法,以表格形式展示: 属性 属性名类型默认值描述minimumCartesian3盒子的最小 x, y, 和 z 坐标。maximumCartesian3盒子的最大 x, y, 和 z 坐标。vertex…

【PHP】PHP使用Modbus-Rut协议与RS485串口通信,向设备发送和接收数据

目录 一、前言 二、开发前说明 三、效果图 四、安装PHP扩展 五、安装phpModbus类库 六、通信逻辑 七、完整实例 一、前言 使用PHP语言与硬件设备通信交互&#xff0c;并向COM串口发送和接收数据。 前面写了三篇关于PHP与RS235和USB端口通信的文章&#xff0c;可以作为参…