深入Linux进程优先级:Nice值与O(1)调度器原理

1. 优先级是什么

优先级就是进程得到某种资源的先后顺序。优先级与权限的区别:

  • 优先级:能获得资源,拥有资源的先后顺序。
  • 权限:能不能获得资源。

1.1 为什么存在优先级

因为资源少,进程多。所以需要优先级来确定谁先拿资源,谁后拿资源。

2. Linux中的优先级

2.1 查看优先级

运行一个进程后使用ps命令来查看,有以下信息:

  • UID:代表执行者的身份,也就是这个进程是由哪个用户创建的。
  • PID:前面文章讲过,进程代号。
  • PPID:父进程代号。
  • PRI:进程的优先级,值越小越早被执行。
  • NI:当前进程的nice值。

2.2 PRI and NI

NI 就是所说的nice 值,表示进程可被执行的优先级的修正数值。加入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值为负数,该进程优先级值就会变小,即优先级变高,则越快被执行。所以在Linux下,调整优先级就是调整nice值。

需要强调的是,进程的nice值与进程优先级不是一个概念,但是会影响到进程的优先级变化,可以理解nice值是进程优先级的修正数据。

2.3 更改nice值

使用top命令,进入后按 "r"->输入进程PID->输入nice值(注意:修改nice值需要root用户)。

查看当前进程

top命令

进入后按 r,输入当前进程PID

输入要修改的nice值(-10)

修改后

再次修改nice值为10(省略了中间过程,因为中途重启了一次进程导致PID不同)

再次修改后发现PID与NI 没有变回80和0 ,而是90和10,因为:

所以即使再次修改nice值为-15,我们所看到的就会是PRI:65NI:-15

其他修改nice值的命令:nice,renice。

2.4 nice值的范围

nice值的取值范围为 -20~19(一共40个级别) 。所以Linux的进程优先级也是有范围的:60~99(也是40个级别)

那么为什么要有范围呢?

  • 因为我们现在使用的操作系统大多数都是分时操作系统,要保证进程之间尽量的公平公正,所以优先级可以变但是要在可控的范围内变,如果优先级可以随意调整的话,那么就可能出现有的进程永远不会被调度的情况,这种情况也叫做饥饿问题

3. 竞争、独立、并行、并发

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

4. 进程切换

CPU内寄存器就是一套存储空间,寄存器只有一套,属于CPU本身,但是寄存器内部的数据可以有很多。

当前我们使用的操作系统都是分时操作系统,每个进程都有它自己的 "时间片(可以理解为一个计数器)",当时间片到达后,进程就被操作系统从CPU中剥离,进而执行下一个进程。

当进程A暂时被切换出去时,进程A会带走并保存自己在寄存器内的上下文数据,以便下次再调度时候按照之前的逻辑继续运行。

5. 进程调度

一个CPU,一个运行队列(runqueue),在运行队列中存在一个queue[140],它的类型是struct list_head,更好理解一点可以理解成为struct task_struct*,也就是一个指针数组。

图片来源于网络

当我们创建出一个进程后,会根据它的优先级插入到指定位置,这样当CPU调度进程的时候,实际上就是按顺序调度,但是初始创建的进程优先级都是80,所以假如运行队列中只有queue[120]的位置存在大量进程,其他位置没有进程呢?岂不是还需要花时间遍历。

从图片中可以看到queue上方还有一个bitmap[5](位图),每个比特位代表了queue中对应位置是否存在进程,所以当需要调度进程时就查这一个位图,从而提升效率。

上面还有两个指针,分别是*active*expired*active指针就指向了活跃进程这个结构,*expired指向了过期进程的结构,所以:

  • CPU调度的时候,直接通过*active找到对应的queue[140],新增进程、或者时间片到了的进程,被从CPU上剥离,链入到过期进程的队列中。
  • 当活跃进程中所有进程都被执行完毕后,交换*active*expired两个指针指向的内容,从而能再次执行。

这时就可以知道为什么要有nice值了:当前进程在活跃进程时如果调整优先级还要进行移动操作,有了nice值后,只需要当前进程时间片到达后,加上nice值,按照调整后的优先级直接链入到过期进程中,等待下一轮再被调度时,就会直接按照调整后的优先级来调度。

那么在这种调度算法下会存在饥饿问题吗? 很明显不存在这种问题,因为在局部内(也就是每一轮调度)都会将当前所有进程调度完一遍后,再调度下一轮,即使某一个进程优先级特别高,但也要等上一轮调度完才能被调度,这就做到了局部上根据优先级调度,整体上不会造成饥饿问题。 这就是为什么要使用两个队列的原因。

相关推荐
A小辣椒1 天前
TShark:Wireshark CLI 功能
linux
A小辣椒2 天前
TShark:基础知识
linux
AlfredZhao2 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334663 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪3 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5203 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩3 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言