linux内核调度算法(1)--快速找到最高优先级进程

为何要了解内核的调度策略呢?呵呵,由于它值得咱们学习,不算是废话吧。内核调度程序很先进很强大,管理你的LINUX上跑的大量的乱七八糟的进程,同时还保持着对用户操做的高灵敏响应,若是可能,为何不把这种思想放到本身的应用程序里呢?或者,有没有可能更好的实现本身的应用,使得操做系统可以以本身的意志来分配资源给本身的进程?算法



带着这两个问题来看看KERNEL。首先回顾上咱们开发应用程序,基本上就两种类型,一、IO消耗型:好比hadoop上的trunk服务,很明显它的消耗主要在IO上,包括网络IO磁盘IO等等。二、CPU消耗型,好比mapreduce或者其余的须要对大量数据进行计算处理的组件,就象对高清视频压缩成适合手机观看分辨率的进程,他们的消耗主要在CPU上。当两类进程都在一台SERVER上运行时,操做系统会如何调度它们呢?如今的服务器都是SMP多核的,那么一个进程在多CPU时会来回切换吗?若是我有一个程序,既有IO消耗又有CPU消耗,怎么让多核更好的调度个人程序呢?


又多了几个问题。来看看内核调度程序吧,咱们先从它的优先队列谈起吧。调度程序代码就在内核源码的kernel/sched.c的schedule函数中。
首先看下面的优先级队列,每个runqueue都有。runqueue是什么?下面会详细说下,如今你们能够理解为,内核为每一颗CPU分配了一个runqueue,用于维护这颗CPU能够运行的进程。runqueue里,有几个成员是prio_array类型,这个东东就是优先队列,先看看它的定义:服务器

 



看看BITMAP_SIZE是怎么算出来的:#define BITMAP_SIZE ((((MAX_PRIO+1+7)/8)+sizeof(long)-1)/sizeof(long))
那么,LINUX默认配置(若是你用默认选项编译内核的话)MAX_PRIO是140,就是说一共内核对进程一共定义了140种优先级。等待某个CPU来处理的进程中,可能包含许多种优先级的进程,但,LINUX是个抢占式调度算法的操做系统,就是说,须要调度时必定是找到最高优先级的进程执行。上面的BITMAP_SIZE值根据MAX_PRIO算出来为5,那么bitmap实际是32*5=160位,这样就包含了MAX_PRIO的140位。优先级队列是怎么使用的?看2649行代码:idx=sched_find_first_bit(array->bitmap);这个方法就用来快速的找到优先级最高的队列。看看它的实现能够方便咱们理解这个优先级位的设计:网络

 


那么__ffs是干什么的?函数

 


sched_find_first_bit返回值就是最高优先级所在队列的序号,与queue是对应使用的哈,queue=array->queue + idx;这样就取到了要处理的进程队列。这个设计在查找优先级时是很是快的,很是值得咱们学习。


好,优先级队列搞明白了,如今来看看runqueue,每一个runqueue包含三个优先级队列。oop

 


LINUX是一个时间多路复用的系统,就是说,经过把CPU执行时间分红许多片,再分配给进程们使用,形成即便单CPU系统,也貌似容许多个任务在同时执行。那么,时间片大小假设为100ms,太短过长,过长了有些不灵敏,太短了,连切换进程时可能都要消耗几毫秒的时间。分给100个进程执行,在全部进程都用完本身的时间片后,须要从新给全部的进程从新分配时间片,怎么分配呢?for循环遍历全部的run状态进程,重设时间片?这个性能没法容忍!太慢了,跟当前系统进程数相关。那么2.6内核怎么作的呢?它用了上面提到的两个优先级队列active和expired,顾名思义,active是还有时间片的进程队列,而expired是时间片耗尽必须从新分配时间片的进程队列。


这么设计的好处就是不用再循环一遍全部进程重设时间片了,看看调度函数是怎么玩的:性能

 



当全部运行进程的时间片都用完时,就把active和expired队列互换指针,没有遍历哦,而时间片耗尽的进程在出acitve队列入expired队列时,已经单独的从新分配好新时间片了。


再看一下schedule(void)调度函数,当某个进程休眠或者被抢占时,系统就开始调试schedule(void)决定接下来运行哪一个进程。上面说过的东东都在这个函数里有体现哈。学习

 


固然,在咱们程序中,也能够经过执行如下系统调用来改变本身进程的优先级。nice系统调用能够改变某个进程的基本优先级,setpriority能够改变一组进程的优先级。操作系统

相关文章
相关标签/搜索