当前位置:首页 > 嵌入式 > 嵌入式硬件
[导读]Linux的内核开发是一个漫长的过程,自2001年11月开发出2.5.0以来,Linux内核的发展十分迅速,作了很多重大的改进,性能也有了很大的提高。内核调度器的改进是最主要的进步之

Linux的内核开发是一个漫长的过程,自2001年11月开发出2.5.0以来,Linux内核的发展十分迅速,作了很多重大的改进,性能也有了很大的提高。内核调度器的改进是最主要的进步之一,本文对比研究了Linux2.4和Linux2.6的调度器,全面剖析了Linux2.6对调度器的改进。

一个成功的调度器的基本要求可以概括为以下三点:

(1)减少花在调度上的时间,以增加花在执行程序上的时间;

(2)在多处理器系统上,保持处理器的负载平衡;

(3)对交互式应用有良好的响应速度。

但是,一个成功的调度器是很难设计好的,因为一个真正投入运行的系统受到很多因素的制约。相对于Linux2.6,Linux2.4的调度器有很多的不足之处,2.6版本的Linux内核使用了新的调度器算法,称为0(1)算法,它在高负载的情况下执行得极其出色,并且当有很多处理器时也可以很好地扩展。

O(n)算法,O代表order,括号里的数字代表最坏情况下算法效率的上限取决于算法涉及到的元素的个数,O(1)说明是一个常数,在这种情况下,每次调度的效率是一样的,与涉及的元素的多少没有关系,O(n)表示算法效率取决于算法涉及元素的个数。

1 Linux2.4的调度机制

Linux2.4的调度机制可以用下面的算法来描述,示意图如图1所示。

 

 

所有的就绪进程都在一个全局的就绪进程队列中,这个队列没有任何有意义的排序;时间片重算算法是在所有的进程都用尽它们的时间片以后才重新计算。整个队列由一个读/写自旋锁(read/write spinlock)保护着,这样多个处理器可以并行访问,但同时提供写操作的互斥访问。

由算法可以看出,Linux2.4的调度算法可以说是一个O(n)算法,因为调度器挑选执行进程的开销是随系统中就绪进程 的增长而线性增长的。同时,当系统中有多个处理器时,访问就绪进程队列就成了瓶颈,性能也会显著的下降。因而有很多的缺点:

(1)每次调度时,调度器都要线性遍历这个队列,以找出最值得运行的进程执行:当系统负载很高的时候。可执行进程队列会很长,线性搜索的时间是线性增长的,这个时间会很长,当这个时间足够长的时候,有可能出现多个处理器选择了同一个进程的情况,这样,有些处理器会发现,他选择的进程已经分配了其他的处理器,而不得不重新选择,甚至出现选择运行进程的时间比实际执行进程的时间还要长的情况。

(2)当大多数的就绪进程的时间片都用完而又还投有重新分配时间片的时候,SMP系统中有些处理器处于空闲状态,这将影响SMP的效率。

(3)当空闲的处理器开始执行那些时间片尚未用尽而处于等待状态的进程(如果它们自己的处理器忙)时,会导致进程开始在处理器之间“跳跃”,实时进程或者占用内存大的进程在处理器之间跳跃会严重影响系统的性能。

(4)在一个有很多处理器的系统中,当进程用完它们的时间片以后需等待重算,以得到新的时间片,从而导致大部分的处理器处于空闲状态;这将影响SMP的效率。

因此,不难看出当系统中有大量的可执行进程时,选择一个进程去执行可能要花费较长的时间,系统中有多个处理器的时候,难度就更大了,这种调度,在多处理器或者系统负载比较高的情况下,性能受到影响。

2 Linux2.4调度器性能低下的原因

从上面的分析可以看出,造成Linux2.4调度器性能低下的主要原因如下:

(1)系统中调度算法属于O(n),开销是线性增长的;

(2)只有一个全局的就绪进程队列,对多处理器的伸缩性支持不好;

(3)处理器的亲和性不好,容易导致进程在处理器之间“跳跃”;

(4)时间片的重算循环制约了多处理器的效率。

Linux2.6做了很大的改进,它采用O(1)算法,它在高负载的情况下执行得极其出色,并且当有很多处理器时也可以很好地扩展,不但大大改善了对SMP的支持,同时也兼顾了单CPU或者双CPU系统的要求。

3 Linux2.6调度器的改进目标

为了改善Linux2.4的上述不足,Linux2.6的调度器可以通过提供下列新的特性来改善调度器的性能:

(1)提供完全的O(1)调度算法,也就是说,不管系统中进程数量的多少,调度器中所有的算法都必须在常数时间内完成。

(2)应该对SMP有良好的可伸缩性,理想情况下,每个处理器应该有独立的可执行进程队列和锁机制。

(3)应该提高SMP的处理器亲和性,但是同时也应该有在负载不平衡的时候在处理器间迁移进程的能力。

4 Linux2.6的调度机制

新的调度器都实现了这些目标,具体方法是。基于每个CPU来分布时间片,并且取消了全局同步和重算循环。

每个进程有两个数组,活动就绪进程队列数组和不活跃就绪进程队列数组。每个数组中有140个就绪进程队列(runqueue),每个队列对应于 140个优先级的某一个。由一个位图来指示哪些队列是空的,哪些不是空的,每个队列都是先进先出的(FIFO)。这样,在挑选进程的时候,只要通过 find_first_bit找到第一个不为空的队列,并取队首的进程就可以了。

如果一个进程消耗完了它的“时间片”,就进入不活跃就绪进程数组的相应队列的队尾。当所有的进程都“耗尽”了它的“时间片”后,交换活跃与不活跃就绪进程队列数组的指针就可以了,不需要任何其他的开销。

这样,不管队列中有多少个就绪进程,挑选就绪程的速度是一定的,所以称为0(1)算法,该算法可描述如下,示意图如图2所示。

 

这个算法有很多的优点,简述如下:

(1)每个处理器都有独立的就绪进程队列,各个处理器可以并行地运行Scheduler程序来挑选进程运行,不同处理器上的进程可以完全并行地休眠、唤醒和上下文切换。[!--empirenews.page--]

(2)进程只映射到一个处理器的就绪进程队列中,不会被其他的处理器选中,因而也就不会在不同的处理器之间跳跃。

当然,处理器有时确实需要在处理器之间迁移进程,例如负载不平衡的时候,每个处理器每200ms检查一次其他的处理器是不是处在负载不平衡的状况下,就绪进程队列为空的处理器会每lms检查一次。

但是这种情况并不是频繁的发生,所以处理器的亲和性基本能得到保证。

新的调度器的性能确实有很大提高,一个服务器在多个处理器间传送大量的消息的测试结果如表1所示。

 

从表中可以看出,使用新的调度器,在同样的时间内系统能作更多的事情。

5 Linux2.6调度器的不足

新的调度算法在以下几个方面有待改进。

首先,尽管处理器的速度在很快的发展,但是存储体系的速度发展却是相对比较缓慢,对存储器的操作时间往往形成瓶颈。

调度器给处理器分配进程的时候应该考虑进程的相关性。考虑这样的一种情况:两个进程频繁的通过管道或者共享内存通信,测试表明,它们在同一个处理器上工作会更好,因为不用涉及到把数据从一个处理器的caehe里拷贝到另一个处理器的cache里。而目前的调度器不能保证将这样有着密切联系的进程分配到同一个处理器上。同样的问题也存在于设备的相关性。

其次,仍是进程迁移问题,因为在处理器间迁移不同进程的代价是不尽相同的,所以在迁移进程的时候,应该适当考虑进程的特点。

迁移进程的时应考虑进程的大小(这里是指占有内存资源的大小),迁移进程的时候,并设有考虑到进程占用内存的大小,迁移大的进程到其他的处理器会较严重的影响系统的性能。试想出现这样情况:处理器A把它惟一的大进程迁移到了处理器B,而处理器B上的所有进程都是大进程,存储资源原本就紧张,这样一来,处理器A上的进程存储资源就很丰富。而处理器B则更加槽糕。目前,Linux2.6调度器在迁移进程的时候还没有考虑进程的大小。

最后,当系统检测到需要迁移进程以平衡负载的时候,是不是真的非平衡负载不可呢?当系统的负载不平衡且很轻微的时候,是不一定需要平衡负载的。假设有这样情况:有六个进程要求同时执行完毕,但是系统中只有四个处理器。这样,总有两个处理器有两个进程,而其他两个处理器只有一个进程。这就出现问题,因为系统总是不平衡的,导致总有进程在同处理器间迁移,这也就形成了跳跃。

6 对Linux2.6调度器的几点改进建议

同一个任务队列的进程和同一家族的进程尽量映射到同一个处理器上,因为这些进程之间需要频繁通信的可能性是最大的;还可以动态地调整进程与处理器的映射,当监测出两个处在不同的处理器上的进程频繁通信的时候,就利用每200ms检查负载平衡的计划将它们调整到同一个处理器上。

可以在每个进程的就绪进程位图中存储一些大进程的标志信息,跟本处理器中大进程占的比重来迁出或者迁入大进程。

设置一个调节负载平衡的处理器负载阈值load_threshold,在load_balance函数中检查系统欲调节负载的处理器的实际负载,没有超过事先给定的threshold,就不对这个处理器作真正意义上的负载平衡调节。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

史胜辉,在MTK工作了11年,一直在基带芯片的USB驱动领域做开发和验证。从最开始做USB2.0/3.0 IP验证和驱动开发到后面带领团队做上层协议驱动开发,以及跟硬件设计部门合作开发全新的USB硬件加速器。

关键字: 基带芯片 驱动领域 驱动开发

点击上方名片关注我们朱老师推荐语:此岗位为AIoT终身成长大会员同学提供的自己公司的岗位内推,总部在深圳,是一家专业从事闭路电视监控设备、会议摄像机的研发、制造、销售的高科技企业,有学过嵌入式课程或者海思项目的同学,想换...

关键字: 开发工程师 linux驱动 驱动开发

最近在学习MIPI接口的LCD驱动开发与调试,这里我主要用的是MIPI-DSI接口,它学习起来真的是太复杂了,特别是对于我这种很久都没写驱动来说更是头疼,但是头疼归头疼,工作咱们还是要完成的,那就只能硬着头皮往下肝吧!首...

关键字: MIPI 驱动开发 调试

关注、星标嵌入式云IOT技术圈,精彩及时送达来源|  Linux与SoC整理出了6种驱动开发时与设备注册、设备树相关的调试方法,彼此间没有优先级之分,每种方法不一定是最优解,但可以作为一种debug查找问题的手段,快速定...

关键字: 驱动开发

最近在学习MIPI接口的LCD驱动开发与调试,这里我主要用的是MIPI-DSI接口,它学习起来真的是太复杂了,特别是对于我这种很久都没写驱动来说更是头疼,但是头疼归头疼,工作咱们还是要完成的,那就只能硬着头皮往下肝吧!首...

关键字: MIPI 驱动开发 调试

哈喽,我是老吴,我来继续分享我的学习心得啦。gpio和pinctrl子系统在内核里的使用率非常高,和嵌入式产品的关联非常大。从这两个子系统开始学习驱动开发是个不错的入门选择。本文目录:一、gpio 与 pinctrl二、...

关键字: gp pi 驱动开发

前言 最近,我偷偷潜伏在各大技术群,因为秋招在即,看到不少小伙伴分享的大厂面经。 然后发现,操作系统的知识点考察还是比较多的,大厂就是大厂就爱问基础知识。其中,关于操作系统的「调度算法」考察也算比较频繁。 所以,我这边总...

关键字: 调度算法

前阵子工作上做了一些关于 ADC 的支持,由于现在 ADC 相关的支持都被移动到了 IIO (Industrial I/O) 子系统下,我查阅了一些关于 IIO 资料,包括书籍、文章、内核文档和代码。个人感觉最好的入门文...

关键字: IO 驱动开发 嵌入式

麻省理工学院研究人员开发的一种新型系统自动“学习”如何在数千台服务器上安排数据处理操作 - 这项任务传统上用于不精确的,人为设计的算法。这样做可以帮助当今耗电量大的数据中心更有效地运行。

关键字: 数据中心 AI 调度算法 编码

来源:知乎,作者: 埃尔维斯·刘能 链接:https://www.zhihu.com/question/34686343/answer/308464284 前言:上班划水在知乎看到一个帖子,网友问: 现在要选个方向,嵌入...

关键字: 嵌入式 驱动开发 ADI IC厂商
关闭
关闭