【Linux进程】进程优先级 && Linux 2.6内核进程的调度

目录

前言

[1. 进程优先级](#1. 进程优先级)

[2. 并发](#2. 并发)

[3. Linux kernel 2.6 内核调度队列与调度原理](#3. Linux kernel 2.6 内核调度队列与调度原理)

总结


前言

进程是资源分配的基本单位, 在OS中存在这很多的进程, 那么就必然存在着资源竞争的问题, 操作系统是如何进行资源分配的? 对于多个进程同时运行, 操作系统又是如何调度达到并发呢? 本文将以Linux kernel 2.6为例 , 向大家介绍进程在操作系统中 (OS) 的调度原理;

1. 进程优先级

进程优先级是操作系统中用来确定进程获取 CPU 资源的先后顺序的一种机制;

为什么要排队? 本质是资源不足; 在一台电脑中可能只有一个CPU, 但是可能会同时启动多个进程, 那么进程在分配CPU资源时就需要排队(等待CPU资源);

对于较为重要的进程, 可以设置高优先级, 高优先级进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

使用ps -l查看系统进程:

其中较为重要的信息:

  • UID : 代表执行者的身份
  • PID : 代表这个进程的代号
  • PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
  • PRI :代表这个进程可被执行的优先级,其值越小越早被执行
  • NI :代表这个进程的nice值(在进程PCB中)

Linux中进程优先级范围: 60 ~ 99;

Linux中创建进程,默认进程优先级是 80

在Linux中支持优先级的动态调整, 动态调整的规则:

nice值最小是-20, 超过 -20就统一成 -20;

nice值最大为19, 超过19 统一成19;

优先级(PRI) 的计算 : PRI (new) = PRI (old) + nice ;

PRI+ nice值是基于默认值80计算的(不会累计),比如: 先把nice值设为10,那么PRI就会变成90,使用root账户将nice值设为-10,PRI就变成了70 ;

用top命令更改已存在进程的nice:

  • top
  • 进入top后按"r"-->输入进程PID-->输入nice值

**注意:**OS只允许普通用户把优先级调低, 不允许把优先级调高, root账户无限制;

为什么设置限制?

OS在调度时,为了让每一个进程较为均衡得到调度; 如果nice值可以随意乱改, 就会存在用户恶意的将自己的进程优先级调高,导致优先级低的进程长时间得不到CPU资源 ;

需要注意的点是,进程的nice值不是进程的优先级,PR I和 NI 他们不是一个概念,但是进程nice值会影响到进程的优先级变化。可以理解nice值是进程优先级的修正修正数据

几个较为重要的概念:

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

2. 并发

本文的重点是并发 , 先来介绍一下什么是并发?

一个进程在被CPU调度时, 并不是一直占用CPU直至运行结束 , 而是每隔一段时间(这个时间段也叫做时间片) ,它就会被从CPU上被剥离下来 , 然后会重新放进运行队列等待被调度,如此反复,直到进程运行完毕; CPU每次调度进程时, 都会到运行队列中去取;

Linux内核支持进程之间CPU资源的抢占,它是一种基于时间片轮转式抢占式内核,时间片非常的短,轮转速度非常快(一秒内进程可能被调度了100次),所以我们很难察觉;

新的问题: 进程在运行时会被从CPU上剥离下来, 那下次调度时, CPU是如何知道进程执行到哪里的呢?

小方框表示寄存器;

在CPU当中有很多各种各样的寄存器:eax、ebx、ecx、edx、ss、ds、cs、gs、fs、ebp、esp、eip..

寄存器的功能有很多,比如记录程序/进程的运行状态(走到那一步);

比如: cpu内:eip:程序计数器;

进程在运行时会使用这些寄存器,进程会产生各种各样的数据,在寄存器中临时保存 !

如果有多个进程,各个进程在CPU内形成的临时数据,都是不一样的每个进程运行到哪里,产生的临时数据,叫做进程硬件上下文;

在进行轮转切换时会暂时将这个数据存储到进程PCB里;

注意:

在以前老的Linux中是这样,现在的不是直接保存到PCB,原因是PCB内容太多,太大,但都与PCB有联系,这里只是可以理解为放在PCB当中;本质就是将CPU寄存器当中的数据保存到内存当中;

CPU寄存器硬件只有一套,进程上下文数据有很多套,比如10个进程有10套上下文数据;

寄存器 != 寄存器内容

3. Linux kernel 2.6 内核调度队列与调度原理

有了前边的基础知识补充, 接下来我们介绍一下Linux kernel 2.6 内核调度队列以及基本调度原理;

一个CPU拥有一个runqueue(如果有多个CPU就要考虑进程个数的负载均衡问题)

下图就是Linux2.6内核中进程队列的数据结构:

优先级:

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

100~139就是我们使用指令看到的40个优先级; 从第100号开始(PRI: 60), 优先级依次向下递减;

如下图:

CUP调度队列中的进程是如果直接遍历一遍队列, 然后依次调度进程, 遍历的过程也会造成资源的浪费; 所以在设计时加入了nr_active 和 bitmap[5];

int整形占4个字节,32个bit位 5 x 32 也就是 160个 bit位 (足够表示140个优先级) ; 利用位图映射可以极大的提高效率;

nr_active判断队列是否有进程,bitmap位图映射快速找到进程位置,这样下来轮转一次的效率就会非常高,时间复杂度接近O(1) ;

在操作系统中会维护两个这样的队列 (活动对列 和 过期队列);

进程在活动队列并不一定就运行完了,可能是时间片结束了,被调度完之后就会加入到了过期队列;

同时还会维护两个指针:

  • void *active 活动队列
  • void *expired 过期队列

CPU只会执行active指针指向的队列​​​​​​​

当进程优先级为99的进程正在被执行时,新插入一些优先级较高的进程,这些进程会被插入

到过期队列当中; (如果直接插入到活动队列,那就会导致优先级较低的队列一直等待,进而引发进程饥饿问题)

这样一来, 过期队列的进程不断增多, 由于不会插入新的进程,所以它的进程数量一定会越来越少;当active指针指向的活动队列执行完毕,就将两个指针指向的队列进行交换即可

原本的活动队列执行空了,再来新的进程就插入到这个队列,这个队列会继续作为过期队列

如此循环,最终就完成了进程的调度;

​​​​​​​这样的设计方式不仅提高了效率,并且也解决了进程饥饿问题;


总结

进程是资源分配的基本单位, 在OS中存在这很多的进程, 那么就必然存在着资源竞争的问题, 于是便有了进程优先级来确认进程调度的先后顺序; 但这也可能会伴随着进程饥饿的问题, 而在Linux2.6版本中的进程调度设计很好的解决这些问题; 具有很高的参考学习的价值; 好了以上便是本文的全部内容, 希望对你有所帮助 , 感谢阅读 !

相关推荐
爱知菜35 分钟前
Windows安装Docker Desktop(WSL2模式)和Docker Pull网络问题解决
运维·docker·容器
做测试的小薄41 分钟前
Nginx 命令大全:Linux 与 Windows 系统的全面解析
linux·自动化测试·windows·nginx·环境部署
影龙帝皖2 小时前
Linux网络之局域网yum仓库与apt的实现
linux·服务器·网络
月下雨(Moonlit Rain)2 小时前
Docker
运维·docker·容器
碎忆2 小时前
在VMware中安装虚拟机Ubuntu
linux·ubuntu
农民小飞侠2 小时前
ubuntu 安装pyllama教程
linux·python·ubuntu
打工人你好3 小时前
UNIX域套接字(Unix Domain Sockets, UDS) 的两种接口
服务器·unix
技术小甜甜3 小时前
[Dify] 使用 Docker 本地部署 Dify 并集成 Ollama 模型的详细指南
运维·docker·容器·dify
AI云师兄3 小时前
MCP 实战系列(Day 2)- 动手搓个文件系统 MCP 服务器
服务器·人工智能·ai编程
学习中的程序媛~4 小时前
主服务器和子服务器之间通过NFS实现文件夹共享
运维·服务器