From: 全面解析Linux 内核 3.10.x - 进程调度

伟大的国家之所以伟大,那是因为一切都井然有序。

何谓调度?

调度算法作为内核的几大核心之一,其重要程度可见一斑。
一个形象的比喻是,硬件好比一个国家拥有的资源(水,土地,矿产,石油,能源等)。那么操作系统就好比执政党。而执政党(操作系统)的效率以及能力都是由办事的效率(进程的执行流程)处理事情的方式(进程的资源分配)等来决定.因为ZF的办事效率高了,显著的一个变化就是人民的生产力就上来了(各进程井然有序的运作,事情自然事半功倍)。

ZF(OP)对于处理事件的方式都是有已有的框框架架的,这些框架我们暂时称之为办事情的’策略’,策略的制定皆有国家对应的直属部门去管理。譬如计划生育的政策由计生委管理,升学考试则由教育部管理等等。好的策略往往办事效率高,垃圾的策略则会导致办事效率低下,而且民怨沸腾。
所以看出策略的重要性有多高。
言归正传,让我们来了解了解进程的调度策略。

调度策略

传统unix操作系统的调度算法必须实现几个互相冲突的目标,进程响应时间尽可能快,后台作业的吞吐量尽可能高,尽可能避免进程的饥饿现象,低优先级和高优先级进程的需要尽可能调和等等。决定什么时候以怎样的方式选择一个新进程运行的这组规则就是所谓的调度策略(scheduling policy)。
Linux 的调度基于分时(time sharing)技术,多个进程以”时间多路复用”,方式运行。因为CPU的时间被分成”片”,给每个可运行进程分配一片。当然,单处理器在任何给定的时刻智能运行一个进程。如果当前运行进程的事件片或时限到期时,该进程还没有运行完毕,进程切换就可以发生,分时依赖定时中断,因为进程是透明的。不需要在程序中插入额外的代码来保证CPU分时。

影响调度策略的几个因素
  1. 响应时间
  2. 吞吐量
  3. 避免进程饥饿
调度时候进程的几种类型

首先根据I/O受限(频繁的I/O调度)和CPU受限(频繁的CPU调度),可以将进程归类为以下几类。
1.交互性进程 – 用户交互进程,因此,要花很多时间等待键盘鼠标事件,当接受了输入以后,进程必须被唤醒。否则用户将被发现系统反应迟钝。
2.批处理进程 – 具有很强的调度需要,一般都在后台运行,因为不必很快的要被响应。
3.实时进程 –这些进程具有很强的调度需要,这样的进程决不会被低优先级的进程阻塞,它们应该有一个短期的响应时间,更重要的是,响应效率必须要高。时间变化很小。

典型的I/O受限的程序有(数据库服务器),CPU受限的有(图形绘制程序),在Linux中,调度算法可以明确地确认所有实时程序的身份,但没有办法区分交互式程序和批处理程序。

进程的抢占

Linux的进程是抢占的,如果进程处于RUNNING 状态,内核检查它的动态优先级是否大于当前正在运行进程的优先级,如果是:current的执行被中断,并调用调度程序选择另一个进程运行,当前,进程在它的时间片到期也可以被抢占,此时,当前进程thread_info结构中的TLF_NEED_RESCHED标志被设置,以便时钟中断处理程序中止时调度程序被调用。
被抢占的程序并没有挂起,因为它还处于TASK_RUNNING状态,只不过不得使用CPU。

时间片

时间片的长短对系统性能是很关键的,它既不能太长也不能太短。例如,假定进程切换需要5ms,如果时间片也设置为5ms,那么CPU至少吧50%的时间花费在进程切换上了。
如果平均跑的事件太长,进程看起来就不再是并发执行,例如,。让我们假定吧时间片设置为5s,那么可运行进程的运行大约5s但是暂停的事件更长,通常认为长的时间片会降低交互式应用的响应时间,但这样往往是错误的。然而在一些情况下,一个太长的时间片会降低系统的响应能力。
时间片的选择是一种折中,Linux采取单凭经验的方法,即选择可能长,同时能保持良好的响应能力这样的一个时间片。

调度算法

早期的Linux调度算法非常简单易懂,在每次进程切换时,内核扫描可运行进程的链表,计算进程的优先级,然后选择”最佳”进程来运行,这个算法的主要缺点是选择”最佳”进程锁要的小号的事件与可运行的进程数量相关,因此,这个算法的开销太大,在运行数千个进程的高端系统中要消耗太多的时间。
但是Linux 2.6以后的调度算法就复杂多了,通过设计该算法较好的解决了与可运行进程数量的比例关系,因为它在固定的时间内选中要运行的进程。它也很好的处理了处理器数量的比例关系,因为每个CPU都拥有自己的可运行进程队列,而且新算法较好的解决了区分交互进程和批处理进程的问题,因此,在高负载的系统中,这种体验很明显。

普通进程的调度

每个普通进程都有它自己的静态优先级,调度程序使用静态优先级来估价系统智能这个进程与其它普通进程之间的调度程度,内核用100到139,数字越大表示优先级越低。

新进程总是继承父进程的静态优先级,不过,通过吧某些的nice值,传递给系统调用nice和setpriority.

实时进程的调度

每个实时进程都与一个实时优先级相关,实时优先级是一个范围从1~99的值,调度程序总是让优先级的进程运行,换句话说:实时进程运行的过程中,禁止低优先级进程的执行,与普通进程相比,实时进程总是被当作活动进程,用户可以通过系统调用改变进程的实时优先级。
当有下面事件之一发生时候,实时进程才会倍一个进程取代。
进程被另外一个具有更高优先级的实时进程抢占。
进程执行了阻塞操作并进入睡眠。
进程停止。
进程通过调用系统调用。sched_yield().
进程是基于时间片轮转的实时进程,而且它用完了时间片。

Linux Scheduler

还记得我们在start_kernel 函数中有一句函数为:sched_init()!
内核关于调度器引入了一种称之为完全公平调度程序(Completely Fair Scheduler,CFS),关于调度器的内容我放在下一篇进行阐述;


By: Keven - 点滴积累

Logo

更多推荐