FREERTOS之任务创建删除

声明:该篇文转载自:http://bluefish.blog.51cto.com/214870/158404



       tskTCB结构的定义这里就不再给出来了,需要注意的是其中uxBasePriority元素,它用于解决优先级反转,freertos采用优先级继承的办法解决这个问题,在继承时,将任务原先的优先级保存在这个成员中,将来再从这里恢复任务的优先级。

       两个延时链表的正解 freertos 弄出两个延时链表是因为它的延时任务管理的需要。 freertos 根据任务延时时间的长短按序将任务插入这两个链表之一。在插入前先把任务将要延时的 xTicksToDelay 数加上系统当前 tick 数,这样得到了一个任务延时 due time (到期时间)的绝对数值。但是有可能这个相加操作会导致溢出,如果溢出则加入到 pxOverflowDelayedTaskList 指向的那个链表,否则加入 pxDelayedTaskList 指向的链表。
       xPendingReadyList; 这个链表用在调度器被lock (就是禁止调度了)的时期,如果一个任务从非就绪状态变为就绪状态,它不直接加到就绪链表中,而是加到这个pending链表中。等调度器重新启动(unlock)的时候再检查这个链表,把里面的任务加到就绪链表中。
 
任务管理:
freertos ucosii 不同,它的任务控制块并不是静态分配的,而是在创建任务的时候动态分配。另外, freertos 的优先级是优先级数越大优先级越高,和 ucosii 正好相反。任务控制块中也没有任务状态的成员变量,这是因为 freertos 中的任务总是根据他们的状态连入对应的链表,没有必要在任务控制块中维护一个状态。此外 freertos 对任务的数量没有限制,而且同一个优先级可以有多个任务。
 
任务删除:
任务创建过程前面讲过了,这里就直接看任务删除的工程。 freertos 的任务删除分两步完成,第一步在vTaskDelete 中完成,FreeRTOS先把要删除的任务从就绪任务链表和事件等待链表中删除,然后把此任务添加到任务删除链表(即那个xTasksWaitingTermination),若删除的任务是当前运行任务,系统就执行任务调度函数.第2步则是在idle任务中完成,idle任务运行时,检查xTasksWaitingTermination链表,如果有任务在这个表上,释放该任务占用的内存空间,并把该任务从任务删除链表中删除。
/****************************************************************
** 参数:pxTaskToDelete 是一个指向被删除任务的句柄,这里其实就是等价于任务控制块
** 如果这个句柄==NULL ,则表示要删除当前任务
*******************************************************************/
void vTaskDelete( xTaskHandle pxTaskToDelete )
{
    tskTCB *pxTCB;
    taskENTER_CRITICAL();
    {
         /* 如果删除的是当前任务,则删除完成后需要进行调度*/
        if( pxTaskToDelete == pxCurrentTCB )
        {
            pxTaskToDelete = NULL;
        }
 
         /* 通过传进来的任务句柄得到对应的tcb*/
        pxTCB = prvGetTCBFromHandle( pxTaskToDelete );
        traceTASK_DELETE( pxTCB );
 
         /* 把任务从就绪链表或者延时链表或者挂起链表中删除*/
        vListRemove( &( pxTCB->xGenericListItem ) );
 
         /* 判断任务是否在等待事件(semaphore 消息队列等) */              
        if( pxTCB->xEventListItem.pvContainer )
        {// 如果是,则把它从事件等待链表中删除
            vListRemove( &( pxTCB->xEventListItem ) );
        }
        // 插入等待删除链表
        vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
        // 增加uxTasksDeleted 计数
        ++uxTasksDeleted;
    }
    taskEXIT_CRITICAL();
 
    /* 如果调度器已经运行,并且删除的是当前任务,则调度*/
    if( xSchedulerRunning != pdFALSE )
    {
        if( ( void * ) pxTaskToDelete == NULL )
        {
            taskYIELD();
        }
    }
}
再看空闲任务做的第2 步工作:
static portTASK_FUNCTION( prvIdleTask, pvParameters )
{
    /* Stop warnings. */
    ( void ) pvParameters;
 
    for( ;; )
    {
        /* See if any tasks have been deleted. */
        prvCheckTasksWaitingTermination();
        ……………………………. ÷
* The portTASK_FUNCTION() macro is used to allow port/compiler specific
  * language extensions.  The equivalent prototype for this function is:
  * void prvIdleTask( void *pvParameters );
这里prvCheckTasksWaitingTermination() 就是干这第2步的工作:每次调用它删除一个任务
static void prvCheckTasksWaitingTermination( void )
{                          
    #if ( INCLUDE_vTaskDelete == 1 )
    {              
        portBASE_TYPE xListIsEmpty;
 
        /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
        too often in the idle task. */
        if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 )
        { // 禁止调度
            vTaskSuspendAll();
            //打开调度
            xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
            xTaskResumeAll();
 
            if( !xListIsEmpty )
            {
                tskTCB *pxTCB;
                // 关中断
                portENTER_CRITICAL();
                {          
                    pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) );
                    vListRemove( &( pxTCB->xGenericListItem ) );
                    --uxCurrentNumberOfTasks;
                    --uxTasksDeleted;
                }
                portEXIT_CRITICAL();
               // 释放内存,删除tcb
                prvDeleteTCB( pxTCB );
            }
        }
    }
    #endif

本文出自 “bluefish” 博客,请务必保留此出处http://bluefish.blog.51cto.com/214870/158404

你可能感兴趣的:(FREERTOS之任务创建删除)