μC/OS—Ⅱ任务延时管理的改进

2016-05-14 03:11许璐璐郑吉洲
网络空间安全 2016年5期

许璐璐 郑吉洲

[摘要]嵌入式实时操作系统μC/OS-Ⅱ在时钟节拍服务中,需要遍历任务控制块链表中的所有任务控制块,对任务的延时进行管理,效率比较低。针对这个问题,论文提出了一种改进方法,使用增量链表对任务延时进行高效管理,并给出了增量链表的实现及其在μC/OS-Ⅱ任务延时管理中的运用。

[关键词]μC/OS-Ⅱ;任务延时管理;增量链表

1 引言

μC/OS-Ⅱ是一个源码开放的嵌入式实时操作系统,具有结构精简、可裁剪、可移植性强、多任务可剥夺实时内核等特点,稳定性和安全性能好,在嵌入式领域应用广泛。任务延时是嵌入式实时操作系统中的一个常用操作,可能发生在任务主动让出CPU、等待某一事件发生等情况下。每个需要延时的任务都有自己特定的延时请求,操作系统必须维护申请延时任务的集合,对任务的延时状态、延时时间进行管理。

数据结构的设计对操作系统任务延时管理的效率有很大的影响。本文分析了μC/OS-Ⅱ对任务延时管理的缺点,提出了一个基于增量链表的改进方案,能够实现对延时任务的高效管理。

2 μC/OS-Ⅱ任务延时管理分析

μC/OS-Ⅱ中调用OSTimeDly()可实现对任务的延时,任务的延时时间保存在任务控制块里的OSTCBDly变量中,在时钟节拍服务程序OSTimeTick()中对任务的延时状态进行更新,其部分代码如下(参照μC/OS-Ⅱv2,86版本):

从代码可以知道。需要遍历任务控制块链表中的所有任务控制块,对其中的延时任务进行状态更新,当系统中任务数比较多时,这是个很耗时的操作,效率比较低。

3 使用增量链表对任务延时进行有效管理

3.1 增量链表概述

使计算更高效的方法是使用相对时间而非绝对时间。增量链表包含一个延时任务集合,并且链表是按每个任务的延时时间进行排序,但是每个节点存储的不是任务延时的绝对时间,而是在增量链表中存储任务相对于前一个任务必须延迟的多余的时间。

因此,增量链表中第一个任务的延时键值指定了相对于当前的时间,该任务需要等待的时钟滴答数,其他每一个任务的键值指定了相对于各自的前一个任务。该任务需要等待的时钟滴答数。任务延迟的绝对时间等于增量链表中该任务的键值与该任务之前的所有任务的键值之和。

例如,假设任务A、B、C、D分别请求延迟5、20、50、100个时钟滴答,且假设这样的请求在几乎相同时间做出(即在一个时钟滴答内),图1显示了使用增量链表存储这4个延时任务的情况。

给定一个增量链表,可以通过计算部分键值的和得到每个任务的延时时间。

使用了增量链表后,由于链表中所有后续任务的延时时间都是与第一个延时相关的。因此在时钟节拍服务程序中,只需要递减增量链表第一项的延时键值,不需要扫描整个链表,效率有了很大的提高。当第一项的键值变为0时,表明该任务延时时间已到,需要将其放入就绪表。

3.2 增量链表的实现

为了实现增量链表,在任务控制块中添加项:

声明延时增量链表

SO_TCB*OSDelayList。

插入链表操作,需要计算一个相对延迟,将指定的任务插入到OSDelayList中合适的位置。搜索过程从链表头开始遍历链表,将待插入节点的相对延时值与链表中的节点的值比较,当发现待插入节点的值小于链表中某一节点时,则在该位置插入新节点。每当跳过一个节点时,需要将待插入节点的值减去该节点的值,得到相对延迟量。而当插入一个新节点时,必须在链表的剩余节点中减去由于插入新节点而导致的延时值的改变。即在下一个节点的值中减去新插入节点的值。

例如,假设某一时刻延时链表如图1所示,待插入任务E的延时值为30,则插入过程如图2所示。

插入链表操作关键代码如下:

使用了延时增量链表后,在原来的OSTimeDly()中,延时操作OSTCBCur->OSTCBDly=ticks

则变为:

insert(OSTCBCur,ticks);

在时钟节拍服务程序中,只需递减延时链表第一个节点的键值,当其变为0时,表明其延时时间已到,需要将该任务唤醒:

函数wakeup()需要将延时链表中从第一项开始延时键值为0的所有任务唤醒:

{

清等待状态标志:

if(任务状态为ready)

任务放入就绪表;

ptcb=ptcb->delay_next;

}

OSDelayList=ptcb;

}

当某个任务要取消延时,需将其从延时增量链表中移除,且需要将链表中该节点之后的剩余节点加上由于移除节点而导致的相对延时值的改变,即在下一个节点的键值中加上被移除节点的键值。

4 结束语

增量链表通过使用相对时间而非绝对时间。实现了对延时任务的高效管理,在对时间效率要求较高的实时系统中,有良好的应用效果,也可将其借鉴到其他的应用场景中。