Linux---进程(4)---进程优先级&&调度切换

avatar
作者
筋斗云
阅读量:0

目录

进程优先级

进程切换

前期知识补充

进程切换

进程调度


进程优先级

权限是为了解决能不能享受资源的问题,优先级则是为了解决享受资源的顺序的问题。

进程要访问某种资源,就需要用排队的方式,确定享受资源的先后顺序。因为资源是少数,进程是多数。要想和谐的将这些进程都有序的运行,就必须通过排队的方式。

在Linux中,进程优先级字段是进程信息中的PRI字段。

ps -al #查看当前进程 ps -l  #查看当前进程

Linux中进程的优先级本质就是一个整型变量,默认优先级是80。

进程优先级是可以被修改的,Linux进程优先级的范围是[60,99]。

Linux进程优先级本质就是数字,数字越小,优先级越高。

Linux修改进程优先级是通过NI值间接修改的。

修改进程优先级方法:

1、打开任务管理器

top #打开任务管理器

2、输入r和进程pid

3、设置NI值

最终优先级=初始优先级(始终值80)+NI值

用户只能通过修改NI值间接修改进程优先级。

每次输入的NI值都是被覆盖的。

初始优先级始终是80。

NI值不属于优先级数据,是进程优先级的修正数据。

NI值的大小范围为[-20,19]

如果设置新的NI值超过了系统规定范围,就按照极值来确定。比如NI值输入-100,就被系统默认为-20。

Linux为什么要规定NI值的范围从而使用户间接修改进程优先级呢?

原因是为了限制多人使用资源,从而导致的CPU调度不平衡,优先级高的会先得到资源,导致常规进程很难得到资源所引发进程饥饿问题

所以,任何分时(实时操作系统)的操作系统,在调度上都较为公平的调度。就是为了解决进程饥饿问题。

进程切换

前期知识补充

现代操作系统大致分为

1.分时操作系统:基于时间片轮转处理进程(由调度器完成,调度器基于时间片、优先级轮转执行),CPU公平调度,进程优先级差距不明显。

2.实时操作系统当前进程执行完成之后再执行下一个,所有的进程都按照顺序排队执行,允许进程修改优先级插队执行。

我们日常计算机操作系统一般都采用分时操作系统。

竞争性:进程之间通过优先级竞争资源享用顺序。

独立性:多个进程运行时进程之间相互独立,互不干扰。

并行性多个进程在多个CPU上同时运行,这多个进程之间的关系即为并行。

并发性多个进程在同一个CPU上运行,由于受时间片、进程优先级发生进程轮转,加上CPU处理很快,所以,我们感知多个进程是同时推进执行的,这多个进程之间的关系称为并发。

注意:并行中的多个CPU不是多核CPU,多核CPU还是一个CPU,只是好几个运算器+一个控制器,可以同时处理不同分支的代码和数据。

CPU周围有很多寄存器,这些寄存器各司其职完成CPU执行这个进程时数据的保存工作。

来帮助CPU更好的执行接下来的工作。

进程切换

CPU调度执行进程时,操作系统会为其维护一个运行队列,当一个进程被CPU调度执行时,会将这个进程对应的代码和数据执行处理,处理的一些临时变量等数据保存在对应的寄存器中,eip寄存器中保存下一次执行的代码的地址(也就是PC指针)。放到寄存器中的处理数据都属于通用数据信息,属于进程特有的数据被CPU处理之后会保存在自己进程的PCB中(因为进程具有独立性)。当这个进程的时间片到了之后,CPU就会将处理这个进程所产生的数据信息拷贝到该进程的PCB中,等到下次再次执行到这个进程时,这个进程先将上次的数据信息在CPU寄存器中拷贝回来,这个过程叫做恢复,继续接着上次执行的位置继续执行(这个是eip寄存器保证的)。

进程在运行的过程中,要产生大量的数据,放在CPU寄存器中。

CPU内部的所有临时数据,我们叫做进程的硬件上下文数据

硬件上下文数据让我们的进程PCB进行拷贝称为保护上下文数据

当进程被调度的时候,进程被放到CPU上开始运行,将曾经保存的硬件上下文数据进行恢复。

所有的保存都是为了最终的恢复

所有的恢复,都是为了继续上次的运行位置继续运行

CPU内的寄存器只有一套,每个进程在切换之前就必须将自己在调度过程中CPU处理的上下文数据保存至自己的PCB中,等到再次调度这个进程时恢复,接着上次处理位置继续处理。

虽然寄存器数据放在了一个共享的CPU设备里面,但是所有的数据,其实都是被进程私有的,也就是说,只有进程自己才可以访问这些数据。

所以,寄存器内部保存的数据,可以有多套。

进程调度

进程调度算法要考虑优先级、进程饥饿、效率问题

操作系统在运行队列中维护了一个array结构体数组。通过array结构体数组完成对进程的调度工作,并且设置了两个指针,active指向array[0],expired指针指向array[1],CPU要调度进程只从active中拿数据,通过active指针访问array[0]的调度任务数据。当执行完成active指针指向的调度数据时,交换指针active、expired指针内容,此时,CPU就可以继续调度执行另一个调度数据了。

在CPU处理active指针指向的调度数据时,此时由时间片轮转的进程和新创建的进程进入expired指针所指向的数组中,由此,就可以将先一段时间创建的进程率先执行,后一段时间的进程延后执行。并且同一时间段的进程按照优先级先后顺序执行。

下面研究一下array数组如何管理进程调度

array数组中每个元素都是一个结构体,nr_active表示当前活跃进程个数,bitmap作为后续检测,这个之后再谈,queue数组每个元素位置记录tast_struct指针。

queue数组为进程指针数组,里面的[100,139]元素记录着对应进程地址。根据进程优先级[60,99]映射到queue数组中。比如,进程优先级为60的就映射到queue数组元素下标为100处链接。

bitmap数组通过哈希映射,每个bit位都映射queue数组中PCB指针是否为NULL,0表示该位置指针为NULL,1表示该位置指针为非NULL,可以调度执行,能够更加便捷的寻找出当前还有那个优先级的进程没有被执行。如果没有bitmap数组,就要去遍历queue数组,会降低效率。

下面是整体的过程。

CPU只通过active指针访问调度数据,当前active指向的进程指针数组称为活跃进程,另一个称为过期进程,活跃进程由于进程时间片轮转、进程切换会被链接到过期进程的queue数组中去,活跃进程执行完成之后,会将active指针和expired指针的内容进行交换,CPU再执行下一批进程,由此往复执行进程。

以上就是Linux早期版本的进程调度大致做法。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!