操作系统中的Linux任务调度器——经典调度算法
gudong366 2025-05-08 12:51 7 浏览
一,调度器概述
任务调度器是操作系统中一个很重要的功能部件,主要功能是把系统中的task调度到各个CPU上去执行,满足如下的性能需求:
- 调度器必须是公平的:(对于分时的进程,每个任务都应该有机会执行,不能饿死,保证每个进程得到合理的CPU时间)
- 快速的进程响应时间:(对于交互式进程,需要和用户进行交流,因此对调度延迟比较敏感)
- 高系统的吞吐量:(对于批处理进程进程,属于那种在后台的默默奉献的,因此它更注重吞吐量的需求)
- 功耗要小:(对于移动式终端,功耗的需求其实一直以来都没有特别被调度器重视,当然在linux大量在手持设备上应用之后,调度器不得不面对这个问题了)
对于操作系统,为了达到这些设计目标,调度器必须要考虑某些调度因素,比如优先级、时间片等。很多操作系统的调度器都是采用优先级,调度器总是选择优先级最高的那个进程执行。而在linux内核中
优先级是实时进程调度的主要考虑因素:
对于普通进程,如何细分时间片则是调度器的核心思考点。过大的时间片会一种损伤系统的响应延迟,让用户明显能够感知到延迟、卡顿,从而影响用户体验。较小的时间片虽然有助于减小调度延迟,但是频繁地切换对系统的吞吐量会造成严重的影响。
所以,Linux任务调度器的设计是一个极具挑战的工作,需要在各种有冲突的需求中维持平衡。
二,经典调度算法
1962年由Corbato等人提出了多级反馈队列(Multi-level Feedback Queue,MLFQ)算法,这对操作系统的进程调度的设计产生了深远的影响。很多操作系统的进程调度器(如Solaris、FreeBSD、Windows NT、linux内核的O(1)调度器等),都是以这个多级反馈队列为基本思想。
多级反馈队列算法的核心思想:
把进程按照优先级分成多个队列,相同优先级的进程在同一个队列中
如果进程A的优先级大于进程B的优先级,那么调度器选择进程A
如果进程A和进程B的优先级一样,那么它们同属于一个队列里,使用轮转调度算法来选择
多级反馈队列算法的精髓在于反馈,多级反馈队列算法需要判断进程属于哪种进程,然后做出不同的反馈
当一个新进程进入调度器,把它放入优先级最高的队列里,若这个进程完全占用了CPU,说明这是一个CPU消耗型的进程,那么需要把优先级降一级,将其从高优先级队列中迁移到低一级的队列里
若一个进程在时间片没有结束之前放弃CPU,那么说明这是一个I/O消耗型的进程,那么优先级保持不变
这个反馈算法看起来不错,可是在实际应用过程中还是发现它有不少问题。
第一个问题,会产生“饥饿”,当系统中有大量的I/O消耗型的进程的时候,这些I/O消耗型的进程会把CPU完全占满,因为他们的优先级最高,所以那些CPU消耗的进程就会得不到CPU时间片,从而产生饥饿
第二个问题,有些进程会欺骗调度器,有的进程在时间片快要结束的时候突然发起了一个I/O请求并放弃CPU,按照规则,调度器把这个进程判定为I/O消耗型的进程,从而欺骗调度器,它继续保留在高优先级的队列里面。这种进程其实99.99%的时间在占用CPU时间片,到了最后时刻还巧妙的利用规则来欺骗调度器。如果系统中有大量的这种进程,那么系统的交互性就会变差了
第三个问题,一个进程很难去判断究竟属于I/O消耗型还是CPU消耗型,一个进程可能一会儿是I/O消耗型,一会儿是CPU消耗型
更多Linux内核视频教程文档资料免费领取后台私信【内核】自行获取。
linux调度器演变
3.1 早期版本
Linux0.11版本就已经有一个简单的调度器,当然并不适合现在的多处理器的系统。该调度器只维护了一个全局的进程队列,每次都需要遍历该队列来寻找新的进程执行
3.2 linux内核的O(n)调度算法
linux2.4版本的linux内核使用的调度算法也非常简单和直接,由于每次在寻找下一个任务时,需要遍历系统中所有的任务链表,所以被称为O(n)调度器。首先我们来分析核心代码
对于linux2.4的内核,其实本质跟linux0.11基本类似,只是在用goodness函数会计算一个权重值,它的基本思想是基于进程所剩余的时间片,在加上进程优先级的权重。在计算动态优先级的时候,对进程分为两种情况,实时进程和普通进程,对于实时进程而言,动态优先级等于静态优先级加上一个固定的偏移
而对于普通进程而言,动态优先级的计算就稍微比较复杂,其计算动态优先级的策略如下
总体来说上面的实现,很任意理解
- jiffies是系统开机以来tick的次数(alarm>jiffies说明过期了,重置为0) -
- counter是时间片,单位是tick(时钟滴答),调度器根据couter大小决定优先级(couter越大优先级越高)
- NR_TASKS是task(进程)总数。
其流程为:
- 1 第一次循环是检查一遍alarm()函数,唤醒任何收到alarm传来的signal的没有被阻塞的tasks,将TASK_INTERRUPTIBLE(挂起)改为TASK_RUNNING可执行。
- 2 while(1) 这个死循环一直执行到关机,每次循环先while (–i)找出counter(时间片)最大的task。
- 3 if (c) break;和下面的这些是说如果c为0(所有进程的counter用完了),就重新分配counter。
- 4 最后调用switch_to(next)切换进程。(切换到counter最大的一个)
nice成员就是普通进程的静态优先级,之所以用(20-nice value)表示静态优先级,主要是为了使得静态优先级变得单调上升。Linux为了奖励睡眠的进程,所以睡眠的进程剩余的时间片会较多,因此动态优先级页会高一些,下一次会更容易得到调度执行。
调度器是根据动态优先级来进行调度,谁大就执行谁,我们以普通进程为例
- 如果进程静态优先级较高,即nice值较小,剩余的时间多,那么必定是优先执行
- 如果进程静态优先级较高,即nice值较小,但是所剩余时间片无几,那么可能会让位给剩余时间片较多
所以对于这个权重值,理解如下:
- -1000,表示不要选择该进程运行
- 0,表示时间片用完了,需要重新计算counter
- 正整数,goodness值越大越容易执行
- +1000,表示实时进程,接下来就要选择它运行
3.3 O(n)调度时机
对于2.4的内核,产生调度的时机主要包括以下几个方面
- 1.进程主动发起调度
- 2.在timer中断处理中发现当前时间片耗尽
- 3.进程唤醒的时候
- 4.父进程在fork的时候,其时间片会均分到父子进程,但是如果只剩下一个tick,这个tick会分配给子进程,而父进程的时间片会被清0,这个时候父进程执行就等同于在timer中断处理中发现当前时间片耗尽;如果父进程在fork的时候,时间片较大,父子进程的时间片都不为0,这个时候的场景类似于唤醒进程,向runqueue中添加一个task,从而引发调度
- 5.用户进程主动让出CPU的时候
- 6.用户进程修改调度参数的时候
以上的场景中,除了进程主动调度之外,其他的场景都不是立刻调度schedule函数,而是设定need_resched标记,然后等待调度点的到来。而对于2.4的内核,由于不是抢占式,因此调度点总是在返回用户空间的时候才会到来,当调度点到来的时候,进程调度会在该CPU上启动。
3.4 O(n)调度时间片处理
对于普通进程的时间片处理思路是
每个进程根据其静态优先级可以固定分配一个缺省的时间片,静态优先级越大,分配的时间片越大
一旦Runqueue的进程被调度执行,那么其时间片会在tick到来的时候递减,如果进程时间片耗尽,那么该进程将失去分配CPU资源的资格
Runqueue中的进程的时间片全部被用完之后,也就是调度周期结束,这个时候需要为runqueue中的进程重新设定其缺省的时间片,这样,新的调度周期又开始了
当runqueue中所有进程的时间片耗尽后,这个时候开启一次重新加载进程缺省时间片的过程,如下:
这里的C是遍历runqueue链表之后找到最大的动态优先级,如果它为0,则说明
系统中没有处于可以运行状态的实时进程,所有的可运行状态的普通进程都已经耗尽完了它们的时间片,这个时候就需要重新计算
通过for_each_task遍历系统中的所有进程描述符,不论是否是可运行状态。
对于挂入runqueue链表中的普通进程而言,其当前的p->counter已经是0,因此它获得新的时间片就是nice计算得到的缺省时间片
对于挂人等待队列中处于睡眠状态进程而言,其时间片为p->counter还有剩余,会累积到进程时间片配额中,也算是对睡眠进程的一种奖励,也就是对于内核会奖励睡眠进程。
同时为了防止经常睡眠的交互式进程获得过于庞大的时间片,并不是累积其全部存留的时间片,而是打个对折
新的一个周期开始,消耗的时间片通过timer中断处理,其流程如下:
每一个tick中断到来的时候,进程的时间片都会减1,当时间片是0的时候,调度器剥夺其执行的权利,从而引发一次调度,选择其他时间片不为0的进程,直到runqueue中所有进程的时间片耗尽,又开始新一轮周期。调度器就是这样周而复始,推动整个系统的运作。
4. 总结
O(n)调度器是采用基于优先级的一种调度算法,Linux2.4内核以及更早都是采用这种算法,其定义如下:
就绪队列是一个全局链表,从就绪队列中查找下一个最佳的就绪进程,需要遍历整个就绪队列,花费的时间与就绪队列的进程数量有关,所耗费的时间是O(n),所以该调度器被称为O(n)调度器
对于O(n)调度器:
- 调度器基于优先级设计,每个进程在创建时被赋予一个固定的时间片,当前进程时间片用完后,调度器会选择下一个进程来运行
- 选择next算法非常简单,对于runqueue中所有的进程进行依次比较,选择优先级最高的进程作为下一个被调度的进程
- 每次进程切换时,内核扫描可运行的进程链表,计算优先级,然后选择最佳进程来运行
- 所有进程的时间片都用完后,才会为所有进程重新分配时间片
但是o(n)调度器页面临很多问题:
- 时间复杂度问题,时间复杂度为O(n),当系统中进程很少的时候,性能还可以,但是当系统进程增加后,选择下一个进程会变得越来越慢,从而导致系统整体性能下降;同时当系统中无可运行进程时,重新初始化进程的时间片也是相当的耗时
- 实时进程的运行效率问题,因为实时进程和普通进程在一个列表中,每次查实时进程时,都需要全部扫描整个列表,导致实时进程不是很“实时”
- 因为系统中只有一个runqueue,则当运行队列中的进程少于CPU的个数时,其余的CPU则几乎是idle状态,浪费资源
- cache缓存问题:当系统中的进程逐渐减少时,原先在CPU1上运行的进程,不得不在CPU2上运行,导致在CPU2上运行时,cacheline则几乎是空白的,影响效率。
- SMP扩展问题。当需要picknext下一个进程时,需要对整个runqueue队列进行加锁的操作,spin_lock_irq(&runqueue_lock);当系统中进程数目比较多的时候,则在临界区的时间就比较长,导致其余的CPU自旋比较浪费
相关推荐
- U盘文件被删怎么简单恢复(u盘里的文件被误删了怎么找回)
-
现在这个社会不是靠关系靠路子,主要还是靠实力。刘强在机关工作,人长得帅气,工作能力又强。唯独一样不好,脾气太大,动不动就发火,因为小事常和同事发生口角。一次他火大的差点把办公桌给掀翻了,领导见他野蛮的...
- 不小心删除了一些文件?9 个最佳免费硬盘恢复软件
-
恢复您曾经无意或意外删除的所有文件和数据。您是否曾经错误地删除了一个对您的工作至关重要并导致您丢失所有进度的文件?我们为您提供了一些最好的免费硬盘恢复软件,以帮助您恢复意外删除的文件,以解决您的文件删...
- Studio 中文版:数据救援神器,误删 / 分区损坏 / RAID 恢复一键找回
-
Studio中文版:数据救援神器,误删/分区损坏/RAID恢复一键找回当文件意外删除、分区损坏,或RAID阵列崩溃时,一款可靠的数据恢复工具往往能挽回关键损失。R-Studio中文版...
- 你值得拥有的11款Linux数据恢复工具
-
如果你使用的是Linux操作系统,那么你一定想知道一旦硬盘崩溃的话又该如何保存和恢复数据。其实,现在有很多Linux数据恢复工具可以让我们摆脱数据安全的困扰。小编已经为各位准备好了一些最好的Linux...
- 误删文件内容怎么恢复(误删文件内容怎么恢复回来)
-
在日常使用电脑的过程中,误删文件的情况时有发生。无论是由于操作失误还是病毒攻击,误删文件都会给我们带来不小的困扰。幸运的是,随着技术的发展,误删文件恢复已不再是难题。本文将介绍几款国内外知名的误删...
- u盘如何恢复删除的文件?推荐5款u盘数据恢复软件!
-
在日常生活与工作中,U盘作为便捷的数据存储载体,频繁用于传输和保存各类重要文件。然而,误删文件的情况却时有发生,无论是珍贵的照片、重要的工作文档,还是精心制作的视频,一旦删除,都可能带来不小的麻烦。...
- 怎么恢复删除的数据?5种有效的数据恢复方法汇总!
-
在数字化办公与生活的时代,电脑里的每一份数据都承载着重要信息。然而,一个误操作就可能导致数据被删除,无论是尚未保存的重要文档,还是珍藏多年的照片,都可能瞬间“消失”。但其实,数据删除并不意味着永久丢...
- u盘删除文件怎么找回?5个数据恢复工具汇总,助你巧妙恢复数据!
-
在日常使用U盘的过程中,误删文件的情况时有发生,重要的工作文档、珍贵的照片视频一旦消失,难免让人焦急万分。别担心,只要选对数据恢复工具,被删除的数据仍有找回的可能。下面就为你汇总5款实用的数据...
- Linux下恢复误删文件:思路+实践(linux删除如何恢复)
-
周五篮球群里有人问误删文件了怎么恢复,得知是ext4文件系统之后我推荐了ext4magic这个工具,然后又有人提到了xfs的话怎么办,正好前几天看到DaveChinner在邮件列表里提到了这个问题,...
- 苹果放大招!不用虚拟机了,Mac直接跑Linux容器,开发者效率翻倍
-
苹果这次真给开发者送福利了!今天凌晨(6月10日),苹果在官宣的Containerization框架直接炸了技术圈——Mac现在能原生运行Linux容器镜像了!这可不是虚拟机那种“套娃”方案,而是基...
- 7 款老牌经典软件,值得收藏(经典老歌软件)
-
Calibrehttps://calibre-ebook.com/Calibre是一个电脑电子书管理软件。肯定有人说了,电子书还要管理?那当然了。它的功能更强大的让你想象不到,首先它可以导入PDF,...
- 神仙级的免费开源电子书阅读器,还支持听书功能
-
神仙级的免费开源电子书阅读器,还支持听书功能,极空间部署『KoodoReader』哈喽小伙伴们好,我是Stark-C~前段时间不是给大家分享的电子书管理工具『TaleBook』嘛~,然后就有粉丝私信...
- 如何在Ubuntu系统中重置root密码(ubuntu忘记密码重置root密码命令)
-
很多人有个问题,就是喜欢把密码设置得很长很复杂,结果谁也没防住,却成功防住了自己ヽ(.ˇдˇ;)ノ对于现代人,特别是年轻人,都有过忘记密码的经历吧。在这篇文章中,我们来了解如何在Ubuntu1...
- 5款功能强大的PDF阅读器,让PDF阅读更轻松
-
分享5款功能强大的PDF阅读器,拥有丰富的PDF阅读工具,支持PDF文档划线、笔记、标记等操作,让PDF阅读更轻松!1.嗨动PDF编辑器一款实用的PDF处理软件,不仅可以阅读PDF文档,还能直接编辑、...
- 上班摸鱼利器! 免费好用的电子书阅读器,NAS轻松部署Koodo Reader
-
哈喽,大家好我是生活爱好者。笔者也是一名小说爱好者,平时用手机用某信读书,会员也开了,在家看体验也不错,但是上班的时候,在工作快速完成之后,想摸个鱼用手机就不太方便啦,作为爱折腾的人,必须要工作认真,...
- 一周热门
- 最近发表
- 标签列表
-
- linux一键安装 (31)
- linux运行java (33)
- ln linux (27)
- linux 磁盘管理 (31)
- linux 内核升级 (30)
- linux 运行python (28)
- linux 备份文件 (30)
- linux 网络测试 (30)
- linux 网关配置 (31)
- linux jre (32)
- linux 杀毒软件 (32)
- linux语法 (33)
- linux博客 (33)
- linux 压缩目录 (37)
- linux 查看任务 (32)
- 制作linux启动u盘 (35)
- linux 查看存储 (29)
- linux乌班图 (31)
- linux挂载镜像 (31)
- linux 软件源 (28)
- linux题目 (30)
- linux 定时脚本 (30)
- linux 网站搭建 (28)
- linux 远程控制 (34)
- linux bind (31)