uC/OS-ll 第二讲_任务就绪表 任务调度器

来源:互联网 发布:淘宝黑方假酒 编辑:程序博客网 时间:2024/06/09 22:15

2.4任务就绪表及任务调度

多任务操作系统的核心工作就是任务调度。 每个任务根据其重要程度的不同被赋予一定的优先级。基于优先级的调度法指,CPU总是让处在就绪态的优先级最高的任务先运行。然而,究竟何时让高优先级任务掌握CPU的使用权,有两种不同的情况,这要看用的是什么类型的内核,是不可剥夺型的还是可剥夺型内核。完成任务调度的函数称为调度器,中心思想就是时刻让任务优先级别最高的就绪任务处于运行状态。

 

2.4.1任务就绪表

在Uc/OS-ll中用INT8U的数组来充当任务就绪表,每一位代表一个任务,用二进制0、1代表该任务的就绪状态。

    每个任务的就绪态标志都放入就绪表中的,就绪表中有两个变量OSRedyGrp和OSRdyTbl[]。在OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组中是否有进入就绪态的任务。任务进入就绪态时,就绪表OSRdyTbl[]中的相应元素的相应位也置位。就绪表OSRdyTbl[]数组的大小取决于OS_LOWEST_PR1O(见文件OS_CFG.H)。当用户的应用程序中任务数目比较少时,减少OS_LOWEST_PR1O的值可以降低μC/OS-Ⅱ对RAM(数据空间)的需求量。

    为确定下次该哪个优先级的任务运行了,内核调度器总是将OS_LOWEST_PR1O在就绪表中相应字节的相应位置1。OSRdyGrp和OSRdyTbl[]之间的关系是按以下规则给出的:

当OSRdyTbl[0]中的任何一位是1时,OSRdyGrp的第0位置1,

当OSRdyTbl[1]中的任何一位是1时,OSRdyGrp的第1位置1,

当OSRdyTbl[2]中的任何一位是1时,OSRdyGrp的第2位置1,

当OSRdyTbl[3]中的任何一位是1时,OSRdyGrp的第3位置1,

当OSRdyTbl[4]中的任何一位是1时,OSRdyGrp的第4位置1,

当OSRdyTbl[5]中的任何一位是1时,OSRdyGrp的第5位置1,

当OSRdyTbl[6]中的任何一位是1时,OSRdyGrp的第6位置1,

当OSRdyTbl[7]中的任何一位是1时,OSRdyGrp的第7位置1,

使任务进入就绪态

OSRdyGrp            |= OSMapTbl[prio >> 3];

OSRdyTbl[prio >> 3] |=OSMapTbl[prio & 0x07];

 

 

2.4.2 任务调度器

1.      调度器的主要共作

任务调度器:在就绪表中查找优先级别最高的就绪任务;

实现任务的切换:获取待运行任务的TCB指针、进行断点数据切换

任务级调度器:OSSched()

中断级调度器:OSIntExt()

2.      获得待运行就绪任务控制块的指针

操作系统通过任务控制块TCB来管理任务,被中止任务的任务控制块指针存放在全局变量OSTCBCur中,所以调度器主要获取待运行就绪任务控制块的指针。

 

通过OSSchedLock()OSSchedUnlock()函数给调度器上锁和解锁,上锁一次,变量OSLockNexting加1;解锁一次,变量OSLockNexting减1。

3.      任务切换宏OS_TASK_SW()

断点:任务被中止运行时的位置

断点数据:当时存放在CPU的PC、PSW和通用寄存器等各寄存器中的数据

一个被中止的任务能否正确地在断点处恢复运行,关键在于能否正确地在CPU各寄存器中恢复断点数据;能否正确恢复断点数据的关键在于CPU的堆栈指针SP是否有正确的指向。

任务的切换就是断点数据的切换,断点数据的切换也就是CPU堆栈指针的切换。

 

void OSSched (void)

{

    INT8U y;

 

 

    OS_ENTER_CRITICAL();

    if ((OSLockNesting | OSIntNesting) == 0) {                (1)

        y             = OSUnMapTbl[OSRdyGrp];                 (2)

        OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);                                                              (2)

        if (OSPrioHighRdy != OSPrioCur) {                     (3)

            OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];       (4)

            OSCtxSwCtr++;                                                                                     (5)

            OS_TASK_SW();                                                                                     (6)

        }

    }

    OS_EXIT_CRITICAL();

}

 

2.5 任务的创建

创建任务本质上就是创建一个任务控制块,通过任务控制块把任务代码和任务堆栈关联成一个完整的任务,而且要使任务进入就绪状态并引发任务调度。

 

创建任务的一般方法:

1、先创建一个起始任务,并且赋予它最高的优先级别。

2、调用OSStart()函数

3、在起始任务中,再创建其他任务

注:如果要使用系统提供的统计任务,那么统计任务的初始化函数必须在起始任务中调用。

 

 

2.6 任务的挂起与恢复

 

2.7 其他任务管理函数

2.7.1任务优先级别的修改  OSTaskChangePrio()

 

2.7.2 任务的删除

OSTaskDel()

简单来说,在任务控制块链表中讲任务删除并归还空任务,再在任务就绪表中将该位置0.

 

2.7.3 查询任务的信息

OSTaskQuery()

如果调用该函数成功,将返回OS_NO_ERR,并把查询得到的任务信息存放在结构OS_TCB类型的变量中。

 

 

第二章小结

1、任务由任务控制块、任务堆栈和任务代码三部分组成。系统通过任务控制块来感知和控制任务:任务堆栈主要用来保护和恢复断电;任务代码是一个超循环结构,它描述了任务的执行过程。在创建一个任务时,函数OSTaskCreate()或OSTaskCreateExt()负责给任务分配任务控制块和任务堆栈,并对他们进行初始化,然后把任务控制块、任务堆栈、任务代码三者关联成一个完整的任务。

 

2、系统是按任务就绪表和任务的优先级别来调度任务,执行任务调度工作的是调度器,他负责查找具有最高优先级别的就绪任务并运行它,同时把这个任务TCB指针存放在OSTABCur中。通常,系统在调用API函数和运行中断服务函数程序之后都要调用函数OSSched()来进行一次任务调度。

 

3、任务切换的核心工作是任务堆栈指针的切换

 

4、任务调度器代码的设计,使得它的运行时间与系统中的任务数无关,使之满足实时系统的要求。

 

5、任务的优先级别也是任务的标志

 

6、 应用程序首先应该调用函数OSInit()对全局变量和数据结构进行初始化,以建立US/OS-ll的运行环境。

 

7、应用程序通过调用函数OSStart()开始进入多任务管理的,但在调用函数OSStart()之前,必须至少创建了一个任务。

0 0
原创粉丝点击