Linux内核调度分析(进程调度)

本文介绍了Linux内核的抢占式多任务调度,通过时间片轮转机制分配进程执行时间,并探讨了调度策略,包括I/O消耗型和处理器消耗型进程的优先级处理。此外,还提到了Linux内核中关于进程优先级的nice值和实时优先级的设定。
摘要由CSDN通过智能技术生成

本文是《Linux内核设计与实现》第四章的阅读笔记,代码则是摘自最新的4.6版本linux源码(github),转载请注明出处。

多任务

并发和并行

Linux作为一个多任务操作系统,必须支持程序的并发执行。

分类

1.非抢占式多任务除非任务自己结束,否则将会一直执行。2.抢占式多任务(Linux)这种情况下,由调度程序来决定什么时候停止一个进程的运行,这个强制的挂起动作即为**“抢占”。采用抢占式多任务的基础是使用时间片轮转**机制来为每个进程分配可以运行的时间单位。Linux进程调度

发展历史

Linux从2.5版本开始引入一种名为O(1)的调度器,后在2.6版本中将公平的的调度概念引入了调度程序,代替之前的调度器,称为CFS算法(完全公平调度算法)。

策略

I/O消耗型和处理器消耗型

I/O消耗型进程是指那些大部分时间都在等待I/O操作的进程,处理器耗费型的进程则是指把大多数时间用于执行代码的进程,除非被抢占,他们一般都一直在运行。

为了保证交互式应用和桌面系统的性能,一般Linux更倾向于优先调度I/O消耗型进程。

进程优先级

Linux采用了两种不同的优先级范围。

1.使用nice值:越大的nice值意味着更低的优先级。 (-19 ~ 20之间)2.实时优先级:可配置,越高意味着进程优先级越高。任何实时的进程优先级都高于普通的进程,因此上面的两种优先级范围处于互不相交的范畴。3.时间片:Linux中并不是以固定的时间值(如10ms)来分配时间片的,而是将处理器的使用比作为“时间片”划分给进程。这样,进程所获得的实际CPU时间就和系统的负载密切相关。```
Linux中的抢占时机取决于新的可运行进程消耗了多少处理器使用比,
如果消耗的使用比当前进程小,则立刻投入运行,否则将推迟其运行。


**举例**

现在我们来看一个简单的例子,假设我们的系统只有两个进程在运行,一个是文本编辑器(I/O消耗型),另一个是视频解码器(处理器消耗型)。

理想的情况下,文本编辑器应该得到更多的处理器时间,至少当它需要处理器时,处理器应该立刻被分配给它(这样才能完成用户的交互),这也就意味着当文本编辑器被唤醒的时候,它应该抢占视频解码程序。

按照普通的情况,OS应该分配给文本编辑器更大的优先级和更多的时间片,但在Linux中,这两个进程都是普通进程,他们具有相同的nice值,因此它们将得到相同的处理器使用比(50%)。

但实际的运行过程中会发生什么呢?CFS将能够注意到,文本编辑器使用的处理器时间比分配给它的要少得多(因为大多时间在等待I/O),这种情况下,要实现所有进程“公平”地分享处理器,就会让文本编辑器在需要运行时立刻抢占视频解码器(每次都是如此)。

Linux调度算法
---------

### 调度器类

Linux的调度器是以模块的方式提供的,这样使得不同类型的进程按照自己的需要来选择不同的调度算法。

上面说讲到的CFS算法就是一个针对普通进程的调度器类,基础的调度器会按照优先级顺序遍历调度类,拥有一个可执行进程的最高优先级的调度器类胜出,由它来选择下一个要执行的进程。

#### Unix中的进程调度

存在的问题:

1.nice值必须映射到处理器的绝对时间上去,这意味着同样是瓜分100ms的两个同样优先级的进程,发生上下文切换的次数并不相同,可能会差别很大。优先级越低的进程分到的时间片单位越小,但是实际上他们往往是需要进行大量后台计算的,这样很不合理。2.相对的nice值引发的问题:两个nice值不同但差值相同的进程,分到的时间片的大小是受到其nice值大小影响的:比如nice值18和19的两个进程分到的时间片是10ms和5ms,nice值为0和1的两个进程分到的却是100ms和95ms,这样的映射并不合理。3.如果要进行nice值到时间片的映射,我们必须能够拥有一个可以测量的“绝对时间片”(这牵扯到定时器和节拍器的相关概念)。实际上,时间片是会随着定时器的节拍而改变的,同样的nice值最终映射到处理器时间时可能会存在差异。4.为了能够更快的唤醒进程,需要对新的要唤醒的进程提升优先级,但是这可能会打破“公平性”。为了解决上述的问题,CFS对时间片的分配方式进行了根本性的重新设计,摒弃了时间片,用处理器使用比重来代替它。

### 公平调度(CFS)

出发点:进程调度的效果应该如同系统具备一个理想的多任务处理器——我们可以给任何进程调度无限小的时间周期,所以在任何可测量范围内,可以给n个进程桐乡多的运行时间。

举个例子来区分Unix调度和CFS:有两个运行的优先级相同的进程,在Unix中可能是每个各执行5ms,执行期间完全占用处理器,但在“理想情况”下,应该是,能够在10ms内同时运行两个进程,每个占用处理器一半的能力。

CFS的做法是:在所有可运行进程的总数上计算出一个进程应该运行的时间,nice值不再作为时间片分配的标准,而是用于处理计算获得的处理器使用权重。

接下来我们考虑调度周期,理论上,调度周期越小,就越接近“完美调度”,但实际上这必然会带来严重的上下文切换消耗。在CFS中,为能够实现的最小调度周期设定了一个近似值目标,称为“目标延迟”,于此同时,为了避免不可接受的上下文切换消耗,为每个进程所能获得的时间片大小设置了一个底线——最小粒度(通常为1ms)。

在每个进程的平均运行时间大于最小粒度的情况下,CFS无疑是公平的,nice值用于计算一个进程在当前这个最小调度周期中所应获得的处理器时间占比,这样就算nice值不同,只要差值相同,总是能得到相同的时间片。我们假设一个最小调度周期为20ms,两个进程的nice值差值为5:

* 两进程的nice值分别为0和5,后者获得的时间片是前者的1/3,因此最终分别获得15ms和5ms
* 两进程的nice值分别为10和15,后者获得的时间片是前者的1/3,最终结果也是15ms和5ms

关于上面这个推论,可能有些难以理解,所以我们深入一下,看看在底层nice差值究竟是如何影响到处理区占比的。

首先,在底层,在实际计算一个进程的处理器占比之前,内核会先把nice值转换为一个权重值weight,这个转换的公式如下:

weight = 1024/(1.25^nice)


举个例子,默认nice值的进程得到的权重就是1024/(1.25^0) = 1024/1 = 1024。

这个转换公式保证了我们可以得到非负的权重值,并且nice对权重的影响是在**指数**上的。

好,现在假设我们的可运行进程队列中有n个进程,他们的权重和`w(1)+w(2)+...+w(n)`记为`w(queue)`,那么任意一个进程i最终得到的处理器占比将是`w(i)/w(queue)`。

接着,我们不难推导出,任意两个进程i和j所分配的到的处理器占比的比例应该是`w(i)/w(j)`,经过简单的数学推导就可以得到最后的结果:`1.25^(nice(i)-nice(j))`,这意味着只要两个nice值的差值相同,两个进程所获得处理器占比永远是相同的比例,从而解决了上面的第3点问题。

上述的转换公式参考自:https://oakbytes.wordpress.com/2012/06/06/linux-scheduler-cfs-and-nice

总结一下,任何进程所获得的处理器时间是**由它自己和所有其他可运行进程nice值的相对差值决定的**,因此我们可以说,CFS至少保证了给每个进程公平的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值