uC/OS-III的任务调度算法研究

uC/OS-III的任务调度算法研究 
1. 就绪列表 
1.1 概述 
    准备好运行的任务被放到就绪列表中,如图1.1。就绪列表是一个数组(OSRdyList[]),它一共有OS_CFG_PRIO_MAX条记录,记录的数据类型为OS_RDY_LIST( 见OS.H)。就绪列表中的每条记录都包含了三个变量.Entries、.TailPtr、.HeadPtr。 
    .Entries中该优先级的就绪任务数。当该优先级中没有任务就绪时, .Entries就会被设置为0。 
    .TailPtr和.HeadPtr用于该优先级就绪任务的建立双向列表。.HeadPtr指向列表的头部,.TailPtr指向列表的尾部。 

表中的记录跟任务的优先级有关。例如,如果一个任务的优先级是5,那么当它就绪时会被放入OSRdyList[5] 中。

uC/OS-III的任务调度算法研究_第1张图片

1.2

 

调用

OSInit()

后的就绪列表

 

有多少种优先级,就绪列表中就由多少条记录。每个记录中都有

3

个变量。

Entries

该记录中的任务数。

.PrevPtr

 .NextPtr

用于指向具有相同优先级到

TCB

组成的双向列表。

对于空闲任务,这两个值为

NULL 

。此时任务就绪表如图

1.2

所示。

1.2 调用OSInit()后的就绪列表 
    有多少种优先级,就绪列表中就由多少条记录。每个记录中都有3个变量。Entries为该记录中的任务数。.PrevPtr和 .NextPtr用于指向具有相同优先级到TCB组成的双向列表。对于空闲任务,这两个值为NULL 。此时任务就绪表如图1.2所示。


1.3 添加任务到就绪列表 
    uC/OS-III提供很多服务可以把任务添加到就绪列表中。最明显的服务是OSTaskCreate(),它通常创建准备运行的任务并将任务放入就绪列表中。如图1.3所示,就绪列表中该优先级中已经有两个任务了。OSTaskCreate() 就会将这个任务插入到列表的未部。


2. 优先级 
2.1 uC/OS-III简介 
    uC/OS-III是一个可扩展的,可固化的,抢占式的实时内核,它管理的任务个数不受限制。它是第三代内核,提供了现代实时内核所期望的所有功能包括资源管理、同步、内部任务交流等。uC/OS-III也提供了很多特性是在其他实时内核中所没有的。比如能在运行时测量运行性能,直接得发送信号或消息给任务,任务能同时等待多个信号量和消息队列。 
    以下列出uC/OS-III相对于uC/OS-II来说最大个改变:

    1> 时间片轮转调度 

    uC/OS-III允许多个任务拥有相同的优先级。当多个相同优先级的任务就绪时,并且这个优先级是目前最高的。uC/OS-III会分配用户定义的时间片给每个任务去运行。每个任务可以定义不同的时间片。当任务用不完时间片时可以让出CPU给另一个任务。

    2>任务数无限制 
uC/OS-III对任务数量无限制。实际上,任务的数量限制于处理器能提供的内存大小。每一个任务需要有自己的堆栈空间,uC/OS-III在运行时监控任务堆栈的生长。uC/OS-III对任务的大小无限制.

    3> 优先级数无限制 
    uC/OS-III对优先级的数量无限制。然而,配置uC/OS-III的优先级在32到256之间已经满足大多数的应用了

2.2 uC/OS-III的优先级调度 
    图2-1到2-3显示了优先级的位映像组。它的宽度取决于CPU_DATA的数据类型(见CPU.H),它可以是8位 、16位、32位,根据处理器相应地设定。 
    uC/OS-III支持多达OS_CFG_PRIO_MAX种不同的优先级(见OS_CFG.H)。在uC/OS-III中,数值越小优先级越高。因此优先级0是优先级最高的。优先级
    OS_CFG_PRIO_MAX-1的优先级最低。uC/OS-III将最低优先级唯一地分配给空闲任务,其它任务不允许被设置为这个优先级 。当任务准备好运行了,根据任务的优先级,位映像表中相应位就会被设置为1。如果处理器支持位清零指令CLZ,这个指令会加快位映像表的设置过程。 
    OS_PRIO.C中包含了位映像表的设置、清除、查找的相关代码。这些函数都是uC/OS-III的内部函数,可以用汇编语言优化。



    为了确定就绪列表中优先级最高的任务,位映像表会被扫描,通过OS_PrioGetHighest()函数找到优先级最高的任务。代码如下所示:


    1) OS_PrioGetHighest() 函数扫描OSPrioTbl[]表直到找到非0的记录。这个循环最终会停止,因为总是有非0记录(空闲任务的存)。 
    2) 当这个表中全是0记录时,就会从下一个表中查找。优先级"prio"会被增加(如果表长32位,就将prio加上32)。 
    3) 当找到第一个非0位时,计算该位之前0位的个数,返回该优先级值。如果CPU提供清零指令,可以通过这个指令优化代码。如果CPU没有这个指令,那么这个指令就只能用C语言模拟了。 
    4) 函数CPU_CntLeadZeros()统计了CPU_DATA记录中0的个数 (从左边开始,以位计)。例如,假定位映像表长32位,0xF0001234返回的非0位前0位数的个数是0。0x00F01234返回的是8。

3. 调度 
    调度器,决定了任务的运行顺序。uC/OS-III是一个可抢占的 , 基于优先级的内核。根据其重要性每个任务都被分配了一个优先级。uC/OS-III支持多个任务拥有相同的优先级。 “可抢占的 ”意味当事件发生时,如果事件让高优先级任务被就绪,uC/OS-III马上将CPU的控制权交给高优先级任务 。因此,当一个任务提交信号量、发送消息给一个高优先级的任务(若该任务被就绪了),当前的任务就会被停止,更高优先级的任务获得CPU的控制权。类似的,当ISR提交信号量或发送消息给一更高优先级的任务(若该任务被就绪了),那么中断返回的时候不会返回到原任务,而是高优先级任务。



你可能感兴趣的:(μC/OS,II,的那些事)