后台任务调度剖析

对于操作系统或者其他相关平台来说,在同一时间内有多个任务需要等待执行,那么作为服务端如何对这些任务进行响应调度是一个问题?

假设处理系统或者平台只能一维调度,也就是说在一个时刻只能运行一个任务,那么我们就面临如何选择执行的问题了?这实际就是排队问题。

最简单的方法就是谁先来先响应,这种调度方式能够很好的保证先来的请求得到响应。并且实现方式简单,不易发生冲突。但是这样调度方式会使得有紧急请求得不到响应,另外短小的进程也会等待很长时间。对于整个操作系统来讲是很不利的。

这就像医生(处理器)做手术(执行)一样,最简单的方式就是排队,谁(线程或者进程)先来先给谁做手术。但是如果前面几个都是些头疼发热的小问题,而新来的一个病人危在旦夕。如果按照这种方式来进行排队,那么将会造成灾难性的后果。另外一种情况是,假如排在队伍前面的是一个费时一天的手术,而后面9个都是只需几秒钟解决的手术(极端情况举例,现实情况肯定不是这样的)。如果采用这种方式,除了第一个病人不需要等待,其他的病人都需要等待一天。如果颠倒顺序,那么可能就9个都需要等待少量时间,吃亏的是需要长时间诊断的那个病人。当然这中分配方式是需要病人们自己预估自己被手术需要的时间,而准确的时间是在手术之后才能确定的。这会制约这种算法适用性。

针对上述的第一种情况,可以采用优先级的概念。每个任务到来时,需要根据其任务性质分配静态的优先数。而针对第二种情况,可以采用加权的方式,其优先级随着等待时间的增加而增加。这些优先级的基础就是对任务进行分割,调度掌握主动权。

这样,病危的病人到来时,就可以优先得到处理。而等待时间长的病人也能得到妥善处理。但问题是如果任务不可分割,调度不掌握主动权,那么就会出现,医生看到病危病人而不能及时抢救,一个病人看不完就不能给其他病人看病的尴尬,遇到脾气不好的病人把医生给揍一顿,整个系统就可能崩溃。这就是微处理器常采用的时间片抢先式任务调度的方法。抢先式任务调度是指当一个任务的时间片用完或者执行完毕,微处理器抢先掌握时间片的控制权,并查看任务的优先级,并将时间片分配给它。所以时间片就成了很关键的问题,如果时间片过长,就会跟没有切割任务有什么区别,高级别的任务不能得到及时有效的执行。时间片过短就会导致频繁的切换而浪费资源时间。时间片的选择式正好大多数任务能够在这个时间片范围内能够得到执行完毕。由于时间片的存在,使用这种方式的调度系统并不是严格意义上的实时系统。飞控等对实时性要求更高的应用常常采用实时性更强的系统。中断将是一个不错的选择。

优先级的问题关键是在任务中查找优先级最高的那个任务,这就涉及到快速查找的问题了。如果所有的任务放在一个链表中,Hash链表将是一个不错的选择。具体的算法后面将会展开。

如果医生有多个,任务调度就会更加复杂。这时候不仅仅要解决先给谁看的问题,还要解决谁给看的问题。这就会出现二维调度问题,这在多处理器的系统是经常出现的。

就如病人的优先级一样,医生们也需要解决谁优先执行的问题。

最简单直接的想法是每个医生都是平等独立的,每个医生有自己独立工作的房间和设备。虽然有点相似多家医院,但是这些医生公用一个大楼,门也是一样的,剩下很多成本。但是这种系统是有问题的。首先假如只有一个病人来看病,那么一个医生将对其看病,其他人都闲着的情况出现,另外假如该医生的设备不够,其他医生充足,但是由于每个医生独立自主,那么就会出现改医生累死,其他医生闲死的情况出现。最可怕的是每个医生都拥有对大门具有开关的权利,如果医生们想法不一致,将会导致医院的大门开关不一致的情况。

另一种想法是医生们选出一个院长,负责给医生发放任务,并且负责对大门的开关。这样就解决了上述的问题。但是这也会引入另外一个问题,当病人很多时,会把院长给累死,其他医生还是很闲的情况。

为了避免上述两种情况的出现,医生们共享了资源并共同管理。医生们共享资源,共同管理共同调度。这就是计算机处理的对称多处理结构。但是这也会出现问题,当两个医生都想去使用某一个设备时就会出现冲突。这是可以利用临界区的概念来解决这个问题,就是在一个设备在被使用时,不允许其他的医生使用它。当使用这个设备的医生不再使用这个设备时,另外一个医生才能够使用。现在大多数处理器都采用的时这种方式。

医生们的关系和病人的关系都处理好了,那么病人和医生之间又是如何安排呢?哪个医生给哪个病人看呢?

最简单的就是病人来了谁闲着谁给看,这种方法非常高效便捷且易于实现。但是当任务有关联,就是说当一个病人有很多病时。(这里主要是为了便于理解任务组,如果仅仅从组的概念应该理解为一群病人,但是一群病人不如一个病人拥有一堆病来的关联性大。毕竟哪有一群病人相约一起来看病,又都看完一起才离开的一群病人呢?换成是一个病人多个病是不是好理解些)医生看完一种病或几种,他们就去处理那些病情稍微重要的病人。这种方式就会导致这个人看好病需要很长时间(直到最后一种病看完,这个病人(任务组)才算完成)。这就是分时调度。

分时调度里面有一个叫做分级调度的概念,类比到这个例子就是病人在看完病时,下次再来看病的时候,上次诊断的医生将会优先被安排给该病人看病。这回提高效率,这是因为该医生对病人还残留某些记忆(高速缓存中还有某些数据块),使得他们的亲和力更强。当然这是再其它病人都忙的情况下,这种对病人进行两次(空闲比较一次,亲和力一次。)安排的方法就是两级调度。每个医生都会建立一个小型的病人排队(线程队列,也叫做线程池)。

所以另一种想法是专家会诊,当病人到来时,医生们如果不够病人的病种数,就是说此时不能够一下子把病人的病给看完。那么这个病人将等待,直到空闲的医生足够多。此后,医生们开始对这个病人进行会诊。中间假如病人某种病,需要进行长时间的病情回忆,那么诊断这种病的医生也不能离开去服务其他病人。诊断完病人的医生可以离开服务其他病人。这种调度在病人多的时候就变得不靠谱,因为不可能正好空闲出那么多医生为这一个病人服务,那么一个医生空闲,他不可能为了这一个病人而一直等待其他医生来会诊这个病人,他很可能马上去诊断下一个病人了。这样,这个病人的病情将一直被延迟。时间长了肯定不是一件好事情。这时候,设立一个中心服务台就显得比较重要,中心服务台一直记录医生空闲的数量,而病人需要周期性的请求服务台,服务台通过调整其他病人的请求来满足该病人的请求。这种调度方式将会使得这种调度更加优化,这实际上也是分级调度的思想。这就是空间共享调度方式。

如果空间共享的方式进行调度时出现不同医生(处理器)诊断病情(响应处理的线程)时出现需要等待对方医生处理结果才能进行下一步诊断的情况,这对整个会诊时不利的。为了更加有效的利用这些医生们,综合分时调度和空间共享调度方式,提出了一种群调度的策略。把所有需要等待结果的病情(需要通信的线程)同时分别交给不同医生(多处理器)处理。这样,一个时刻能够大量通信而减少时间消耗,进而提高系统性能。


猜你喜欢

转载自blog.csdn.net/wangyhwyh753/article/details/79761626