【Linux】进程优先级和Linux内核进程调度队列的简要介绍

进程优先级

  • 基本概念
  • 查看系统进程
  • 修改进程的优先级
  • Linux2.6内核进程调度队列的简要介绍
  • 和进程优先级有关的概念
    • 进程切换

基本概念

为什么会存在进程优先级?
  进程优先级用于确定在资源竞争的情况下,哪个进程将被操作系统调度为下一个运行的进程。进程优先级允许操作系统根据进程的相对重要性和需求来分配有限的系统资源。
  在操作系统中,进程优先级是指操作系统调度器为每个进程分配的优先级级别

查看系统进程

在Linux中可以使用ps -l指令查看有关进程优先级的信息
在这里插入图片描述
同时,我们需要知道几个比较关键的i信息

  • UID 表示执行者的身份
  • PID 当前进程的id
  • PPID 当前进程父进程的id
  • PRI 当前进程的优先级
  • NI 当前进程的nice值

修改进程的优先级

  当我们需要修改进程的优先级时

  1. 输入top指令
  2. 输入r,然后再输入进程PID,最后输入nice值

在 Linux 中,执行 top 命令后按下 r 键,表示向 top 命令发送一个重新调度进程的信号。这个操作通常会让 Linux 内核尝试重新分配 CPU 时间片给进程,以优化系统的性能。
在这里插入图片描述

  • PRI还是比较好理解的,就是进程的优先级(这个值越小,就表示优先级越高)

  • NI就是nice值,表示的就是进程可被执行的优先级的修正数值

  • PRI计算规则如下:
    P R I ( n e w ) = P R I ( o l d ) + n i c e PRI(new)=PRI(old)+nice PRI(new)=PRI(old)+nice
      所以当nice值为负数的时候,就会使得PRI变小,从而使优先级变高。所以,调整进程优先级,实质上就是调整进程的nice值

  • nice的取值范围是[-20,19],一共40个级别

为什么调整进程优先级要受限制?
  如果不加以限制,将某个进程调整的很高,而其他的进程调整得很低,优先级高得进程,会优先获得资源,但是后续产生的常规进程就很难享受到CPU等资源,就会产生进程饥饿问题

注意

  • 进程的nice值不是进程的优先级,它们不是一个概念,但是进程NI会影响到进程优先级的变化

Linux2.6内核进程调度队列的简要介绍

在这里插入图片描述
  以上就是Linux2.6内核中进程调度队列的数据结构
  一个CPU只有一个runqueue
  首先看到活跃进程,进程中queue[140]是一个指针数组,这个数组中,下标从0到99是不使用的,只会使用下标100到139,这也正好对应了进程优先级一共有40个优先级。
  queue中每个元素都是指针,指针指向的是一个链表的头节点,而链表的每个结点都是一个task_struct的结构体,也就是pcb对象,相同优先级的进程的pcb对象就会被放到同个队列中。因此,我们可以将这个queue看作是这样的结构
在这里插入图片描述
  这样,判断活跃进程中是否还有进程,就只需要判断数组下标从100到139位置上是否还存在有效的队列地址就可以了
  但是,如果每次都是遍历整个数组的话,效率上又不太高,于是又添加了一个数组bitmap,这个数组有5个元素,且每个元素的类型都是int。由于int类型有32个bit位,所以整个数组就相当于是拥有了160个bit位,这个数组的意义就是通过bit位的位置来记录数组中所对应下标所指向的队列是否为空。(若队列不为空,则对应的bit位为1否则为0)
  举个例子,将整个数组所对应的bit为看作是一个整体,若第120个bit位为1,则说明queue数组中下标为120的元素所指向的队列中还存在进程(因为数组中一共有140个元素,所以需要至少140个bit位才能表示),变量nr_active表示当前是否有进程需要运行
  所以,CPU维护进程队列中的进程大致过程如下:首先看nr_active,看是否有进程,如果有的话,就会去数组bitmap中查看数组queue中哪个下标存在需要运行的进程,最后直接去对应的下标所指向的队列中拿到对应进程的pcb,并开始运行工作。
  当CPU正在执行活跃进程内的进程时,若后面又有了新的进程或者是当前进程的时间片已经被耗尽,为了不妨碍CPU的执行,就会将该进程放到过期队列中。通过上图的进程调度队列我们可以看到,所谓的活跃进程和过期进程实际上是被放到一个数组array上面的,且该数组的元素都是结构体类型。调度队列runqueue中还有两个变量分别是activeexpirea,这两个变量都是结构体指针类型,它们分别指向活跃队列和过期队列。
  随着时间的推进,活跃进程中的进程会不断减少,过期进程的进程会不断增多。操作系统并不会通过数组下标判断哪个是活跃队列哪个是过期队列,而是直接通过activeexpirea两个指针来判断,所以当活跃进程中的进程全部被执行完之后,要轮到过期队列了是,只用交换activeexpirea两个指针的内容即可
总结一下:
优先级:

  • 普通优先级:100~139
  • 实时优先级:0~99(不关心)

活动队列

  • 时间片还没有结束的所有进程都按照优先级放在该队列
  • nr_active: 总共有多少个运行状态的进程
  • queue[140]:一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进行排队调度,所以,数组下标就是优先级!

从该结构中,选择一个最合适的进程,过程是怎么的呢?

  1. 从0下表开始遍历queue[140]
  2. 找到第一个非空队列,该队列必定为优先级最高的队列
  3. 拿到选中队列的第一个进程,开始运行,调度完成!
  4. 遍历queue[140]时间复杂度是常数!但还是太低效了!
    bitmap[5]:一共140个优先级,共140个进程队列,为了提高查找非空队列的效率,就可以用5*32个bit位表示队列是否为空,这样,便可以大大提高查找效率

过期队列

  • 过期队列中的放置的进程都是新增的进程或者是时间片被耗尽的进程
  • 当活动队列中的进程被处理完之后,会对过期队列中的进程重新计算

active指针和expired指针

  • active永远指向活动队列而expired永远指向过期队列
  • 随着时间的推进,活动队列中的进程逐渐变少而过期进程中的进程逐渐变多,当活动队列上的进程被执行完,就会发生两个指针内容的交换,这样过期队列就变成了新的活动队列

O(1)调度
  在系统中查找一个最合适调度的进程的算法的时间复杂度是常数级别的,所以被称之为是进程调度的O(1)算法

和进程优先级有关的概念

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

进程切换

  当一个进程在CPU上运行时,CPU上所有的寄存器就要为该进程服务,由此,在运行期间,CPU中的寄存器会存储大量的临时数据(比如执行到哪一行、返回值是多少…)。在pcb对象中,存在一个字段称之为时间片,这个字段中存的是当前进程还剩多长运行时间,当时间片上的时间被耗尽时,也就是说CPU不会为该进程继续运算,这个时候就需要进行进程切换。
  进程切换之前首先要做的就是保存CPU寄存器中的临时变量(因为下一个进程运算时产生的临时数据会覆盖上一个进程的临时数据),这些临时变量最终都会被暂时保存到pcb中,将CPU内部寄存器与该进程相关的所有数据都称之为该进程的硬件上下文数据,这些数据保存在pcb中,就叫做保护上下文
  一般进程的调度有两种情况

  1. 如果时首次调度:将代码放到寄存器eip中,逐步去执行,并将中间产生的临时变量填充到寄存器中
  2. 如果时二次被调度:先将pcb中保存的硬件上下文数据恢复,然后代码从上次最后一次执行的位置后面开始执行

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

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

相关文章

【java】15:抽象类

当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法,这个方法就是抽象方法,用abstract来修饰该类就是抽象类。 //我们看看如何把Animal做成抽象类,并让子类Cat类实现。 abstract class Animal{ String name; int age; abstract p…

【C++精简版回顾】12.友元函数

1.友元函数 1.class class MM { public:MM(int age,string name):age(age),name(name){}friend void print(MM mm); private:int age;string name;void print() {cout << age << "岁的" << name << "喜欢你" << endl;} }; f…

k8s 进阶实战笔记 | NFS 动态存储类的部署与使用

文章目录 NFS 动态存储类的部署与使用演示环境说明NFS subdir external provisioner准备 NFS 服务器手动部署 NFS Subdir External Provisioner部署 StorageClass验证使用更多信息 NFS 动态存储类的部署与使用 演示环境说明 演示环境信息&#xff1a;单机K3s 1.28.2 操作系统…

Ansible 简介安装

1、概念介绍 Ansible 是一款为类 Unix 系统开发的自由开源的配置和自动化工具。由 Red Hat 公司使用 python 研发&#xff0c;类似于 saltstack 和 Puppet&#xff0c;但是有一个不同和优点是我们不需要在节点中安装任何客户端。它使用 SSH 来和节点进行通信。Ansible 基于 Py…

信号系统之FFT卷积

1 Overlap-Add 方法 在许多 DSP 应用中&#xff0c;长信号必须分段过滤。例如&#xff0c;高保真数字音频需要大约 5 MB/min 的数据速率&#xff0c;而数字视频需要大约 500 MB/min 的数据速率。在数据速率如此之高的情况下&#xff0c;计算机通常没有足够的内存来同时保存要处…

【程序员英语】【美语从头学】初级篇(入门)(笔记)Lesson 16 At the Shoe Store 在鞋店

《美语从头学初级入门篇》 注意&#xff1a;被 删除线 划掉的不一定不正确&#xff0c;只是不是标准答案。 文章目录 Lesson 16 At the Shoe Store 在鞋店对话A对话B笔记会话A会话B替换 Lesson 16 At the Shoe Store 在鞋店 对话A A: Do you have these shoes in size 8? B:…

SQLlabs46关

看看源码 最终我们的id是放到order by后面了 如果我们直接用列去排序 ?sortusername/password username&#xff1a; passward 可以看到顺序是不同的&#xff0c;当然第一列第二列第三列也可以&#xff0c;基本上都是这个原理&#xff0c;那怎么去实现注入呢&#xff0c;我…

Qt程序设计-钟表自定义控件实例

本文讲解Qt钟表自定义控件实例。 效果如下: 创建钟表类 #ifndef TIMEPIECE_H #define TIMEPIECE_H#include <QWidget> #include <QPropertyAnimation> #include <QDebug> #include <QPainter> #include <QtMath>#include <QTimer>#incl…

leetcode hot100 买卖股票的最佳时机1

本题之前采用贪心算法来解决&#xff0c;现在可以采用动态规划来解决&#xff0c;通过dp数组记录每次的状态从而获取到最大的利润。 这里dp数组定义为二维数组 dp[price.length][2]&#xff0c;其中price.length表示第i天&#xff0c;[2]其中有0/1两种状态&#xff0c;[0]表示…

设计模式(五)-观察者模式

前言 实际业务开发过程中&#xff0c;业务逻辑可能非常复杂&#xff0c;核心业务 N 个子业务。如果都放到一块儿去做&#xff0c;代码可能会很长&#xff0c;耦合度不断攀升&#xff0c;维护起来也麻烦&#xff0c;甚至头疼。还有一些业务场景不需要在一次请求中同步完成&…

【LeetCode】【滑动窗口长度不固定】978 最长湍流子数组

1794.【软件认证】最长的指定瑕疵度的元音子串 这个例题&#xff0c;是滑动窗口中长度不定求最大的题目&#xff0c;在看题之前可以先看一下【leetcode每日一题】【滑动窗口长度不固定】案例。 题目描述 定义&#xff1a;开头和结尾都是元音字母&#xff08;aeiouAEIOU&…

python 基础知识点(蓝桥杯python科目个人复习计划51)

今日复习计划&#xff1a;做复习题 例题1&#xff1a;大石头的搬运工 问题描述&#xff1a; 在一款名为“大石头的搬运工”的游戏中&#xff0c;玩家需要 操作一排n堆石头&#xff0c;进行n - 1轮游戏。 每一轮&#xff0c;玩家可以选择一堆石头&#xff0c;并将其移动到任…

【自然语言处理四-从矩阵操作角度看 自注意self attention】

自然语言处理四-从矩阵操作角度看 自注意self attention 从矩阵角度看self attention获取Q K V矩阵注意力分数softmax注意力的输出再来分析整体的attention的矩阵操作过程从矩阵操作角度看&#xff0c;self attention如何解决问题的&#xff1f;W^q^ W^k^ W^v^这三个矩阵怎么获…

安装使用zookeeper

先去官网下载zookeeper&#xff1a;Apache ZooKeeper 直接进入bin目录&#xff0c;使用powerShell打开。 输入: ./zkServer.cmd 命令&#xff0c;启动zookeeper。 zookeeper一般需要配合Dubbo一起使用&#xff0c;作为注册中心使用&#xff0c;可以参考另一篇博客&#xf…

从零开始掌握Docek的基础知识与应用技巧

目录 前言 一.docekr简介 二.docker的环境搭建 查看内核 更新yum源为最新 ​编辑 安装Docker所需要的工具包 设置yum源 下载docker ​编辑 启动Docker并且设置开机自启动 配置镜像仓库 三.docker命令 1.基本命令 2.常用命令 3.docker容器常用命令 Docker创建并启动…

Java中使用Graphics2D实现图片添加文字/图片水印

场景 java实现给图片添加水印实现步骤&#xff1a; 获取原图片对象信息&#xff08;本地图片或网络图片&#xff09; 添加水印&#xff08;设置水印颜色、字体、坐标等&#xff09; 处理输出目标图片。 注&#xff1a; 博客&#xff1a;霸道流氓气质-CSDN博客 实现 1、…

Parquet 文件生成和读取

文章目录 一、什么是 Parquet二、实现 Java 读写 Parquet 的流程方式一&#xff1a;遇到的坑&#xff1a;坑1&#xff1a;ClassNotFoundException: com.fasterxml.jackson.annotation.JsonMerge坑2&#xff1a;No FileSystem for scheme "file"坑3&#xff1a;与 spa…

020—pandas 根据历史高考分段推断当前位次的分数

前言 每年各省都会公布高考「一分一段」表&#xff0c;它是是以「一分」为单位&#xff0c;统计考得该分数的考生人数和累计人数&#xff0c;每一个分数段上有多少人一目了然。考生通过分数分布表可以查询到相关成绩在全市的排名位次&#xff0c;方便对自己进行定位。本例中&a…

嵌入式学习 Day 25

1.线程分离属性: 线程结束后,自动回收线程空间 pthread_attr_init int pthread_attr_init(pthread_attr_t *attr); 功能: 线程属性初始化 pthread_attr_destroy int pthread_attr_destroy(pthread_attr_t *attr); 功能: 线程属性销毁 pthread_attr…

计算机网络实验一 ENSP模拟器使用

实验一 eNSP模拟器的使用 学习目标&#xff1a; 1&#xff09;掌握eNSP模拟器的基本设置方法 2&#xff09;掌握使用eNSP搭建简单的端到端&#xff08;主机&#xff09;网络的方法 3&#xff09;掌握在eNSP中使用wireshark捕获IP报文的方法 4&#xff09;掌握设备的基本配置方…
最新文章