【扫盲向】进程调度

进程调度(扫盲向)

参考了:

  1. [【小神仙讲 操作系统】 | Linux内核 | 进程调度 | nice | 进程优先级 | 通俗易懂 | 快乐小神仙】] https://www.bilibili.com/video/BV1dK411G7Hc/?share_source=copy_web&vd_source=6809974e05da2ac6884b9251fab43087
  2. http://t.csdn.cn/J3n0g

声明

  1. 本文措辞和描述十分不准确,只能让人大致知道有这么个玩意,但这也就是本文的目的,我也是当做预习来写这篇笔记的
  2. 鉴于以后应该不太可能修改了,就发出来吧,免得在本地被我自己误删
  3. 本文也并非一无是处,如果能帮到大家,那就更好了

进程分类

有的地方分为3类:限时进程,实时进程,普通进程,但我看到的大部分地方只分了实时进程普通进程两类,这里取后者

实时进程

顾名思义,进程需要被实时响应,所以其优先级理应更高,以便让CPU早点处理它

就例如我现在用来进行编辑的obsidian,如果不是实时响应,那么就会感觉到卡顿

非实时进程

响应速度较慢,需要较长时间执行,所以优先级可以较低。

例如显示进度条,没必要实时响应,大可以从某一段跳到某一段

上下文切换

为什么要发生上下文切换

一个(单核)CPU上往往跑了多个进程(并发),但这不是真实的,一个CPU在同一时间只能处理一个进程,之所以我们认为他是多进程的,只是因为除了正在处理的那个进程外,其他线程暂时都被挂起来了。

其中用到的是分割时间片的方法,可以理解为是A进程运行了一小段时间,然后将自己的信息保存下来,然后去跑进程B,跑了会进程B后保存进程B的信息,然后读取刚刚保存下来的进程A的信息,继续运行进程A。

其中被保存下来的信息就叫做上下文

上下文的概念和分类

进程的物理实体(代码和数据等)和支持进程运行的环境合称为进程的上下文.

这些信息大概可以分为三类,分别被叫做:

  1. 用户级上下文
  2. 系统级上下文
  3. 寄存器上下文

调度算法

单核_单进程

最早的CPU由于技术限制,只能做到单核单进程

FIFO

first in, first out,就像我们去排队打饭,先到的人先打到饭。CPU按照FIFO调度的话,会按照先后顺序依次调度进程。

这样的好处是逻辑和实现都比较简单,但是劣势也十分突出,当一个需要时间较多的非实时进程排在了一个需要时间较少的实时信号前面,就会导致比较重要的实时进程等待较长时间才能分配到CPU,严重损耗了性能。

STF

对于FIFO的劣势,用另一个逻辑貌似就能很好的解决他:short time first,即进程所需时间短的被先调度。

这样的好处是相对于FIFO来说整体的等待时间下降了,但也下降得有限,因为你并不能保证任何时候短时间进程都比长时间进程来得快,若是长时间的进程(假设分配的时间为i)先到,在 i 时间内,后面的进程还是要等待。

而且,若是此时一个长时间进程正在等待,而后面又到了很多短时间进程,那么该长时间进程的等待时间也显得有些长了。

STCF

为了继续优化,又想出来Shortest Time-to-Completion First的方法,也就是“最短时间完成优先”,这个算法是划时代的,因为他几乎完美解决了FIFO和STF的劣势,还因为他的性质:抢占性

不难看出,前两种算法其实都默认要执行完被分配的时间,故而才会导致多出一些不必要的等待时间,所以STCF调度就从不必要执行完一个完整时间的角度下手。

以小神仙姐姐(参考1的作者)的举例来看:

接着STF劣势的情况:

  • 当长时间进程P1已经运行了10ms,
  • 这时候P2来了,于是进行一次比较:完成进程P1还需要990ms,完成进程P2只需要40ms,所以先执行P2,
  • P2执行完后才执行P1,此时切换上下文回P1了,完成他还需要990ms,此时没有新进程来,P1顺利运行了90ms,
  • 然后P3来了,再次比较:完成P1还需要900ms,完成P3只需要5ms,所以先跑P3
  • P3跑完后,继续运行还剩900ms的P1

但这种算法依旧存在一个问题,也就是STF也存在的P1等待时间过长的问题,试想一下,当后面来一大堆短时间进程,P1就得不停让CPU,最终等待响应P1的时间未免太长。

单核_多进程(并发)

这里就用到了时间片的概念了,简单一点来理解就是把1s时间分成很多更细小的时间单位。

RR

Round-Robin,意思是轮循调度,微观上还是用的STCF的逻辑,但是把宏观上所需的“时间”换成了微观上的“时间片”,最终达成的效果是在一个时间段内所有的进程都被并发调用到了,这样一来,STCF的缺点就被RR补上了

多核_多进程(并行_并发)

调度队列_全局队列

即多个CPU共用一个队列,这样实现简单却需要不断加锁释放锁,这期间降低了性能

调度队列_局部队列

每个CPU都有自己的进程队列,每个CPU从自己的队列中取进程然后执行

优先级

不是所有的进程优先级都一样,毕竟有的进程就是重要一些,你必须要花自己最大限度的力气来维持任何时候都有给他的资源。

所以说,优先级的存在是必然的。

如何查看优先级

ps -l

S:进程的状态
PID:进程的PID号
PPID:进程的父进程PID号
PRI:优先级的值
NI:nice值

nice

nice咋说呢,可以用“友好”来理解,,,nice值越高,该进程越友好,越不会去抢CPU,也就是说得到CPU调度的时间越少,相对的优先级就越低。

其取值范围为:-20~19

nice -n 设定的nice值 进程名

copy原进程得到一个新进程,新进程的nice值为命令指定的nice值,然后用新的进程代替原进程进行后续操作

看小神仙姐姐操作的bash进程,最后ps -l查看好像是nice命令后多了个bash子进程,我自己操作bash进程也是

renice -n 设定的nice值 进程PID号

重新设定指定PID号进程的nice值(需要超级用户权限)

静态优先级
sched.c
/*
 * Convert user-nice values [ -20 ... 0 ... 19 ]
 * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
 * and back.
 */
#define NICE_TO_PRIO(nice)  (MAX_RT_PRIO + (nice) + 20)
#define PRIO_TO_NICE(prio)  ((prio) - MAX_RT_PRIO - 20)
#define TASK_NICE(p)    PRIO_TO_NICE((p)->static_prio)

 sched.h
#define MAX_USER_RT_PRIO  100
#define MAX_RT_PRIO   MAX_USER_RT_PRIO
#define MAX_PRIO    (MAX_RT_PRIO + 40)
#define DEFAULT_PRIO    (MAX_RT_PRIO + 20)

首先需要知道优先级的设定:PRI代表进程优先级的值,PRI越大,优先级越小。

实时进程由于是特殊的响应,需要很快响应,所以PRI在我也不知道为啥是这个数字的[0, 99],优先级较高,普通进程PTR在[100, 139],优先级较弱

动态优先级

内核自己调节,我们管不着

调度器

有点难理解,不写了

但有一点需要说明一下,上面只是一些扫盲内容,真正的调度器,即使是最开始的调度器都不可能像上面的那些算法描述的那么简单,起码我现在见到的SALED_FIFO调度中的高优先级也是会插队的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值