任务可以使用API函数 vTaskDelete() 删除自己或其他任务。
空闲任务的责任是要将分配给已删除任务的内存释放掉。注意:只有内核为任务分配的内存空间才会在任务被删除后自动回收,任务自己占用的内存或资源需要由应用程序自己显式地释放。
void vTaskDelete( xTaskHandle pxTaskToDelete );
其中pxTaskToDelete 被删除任务的句柄(目标任务) 。可参照创建任务时使用 FreeRTOS 的API 函数xTaskCreate(),
portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode,
const signed portCHAR * const pcName,
unsigned portSHORT usStackDepth,
void *pvParameters,
unsigned portBASE_TYPE uxPriority,
xTaskHandle *pxCreatedTask );
其中pxCreatedTask 用于传出任务的句柄。这个句柄将在API 调用中对该创建出来的任务进行引用,比如改变任 务优先级,或者删除任务。如果应用程序中不会用到这个任务的句柄,则pxCreatedTask 可以被设为NULL。
任务可以通过传入NULL值来删除自己。
例程如下:
/* main() 函数实现 */
int main( void )
{
/* 任务1创建在优先级1上 */
xTaskCreate( vTask1, "Task 1", 1000, NULL, 1, NULL );
/* 任务1以优先级 1创建 */
/* 开启任务调度器,执行任务1 */
vTaskStartScheduler();
/* main() should never reach here as the scheduler has been started. */
for( ;; );
}
/*任务1 代码*/
void vTask1( void *pvParameters )
{
const portTickType xDelay100ms = 100 / portTICK_RATE_MS; /*当前的每个tick的MS值为100*/
for( ;; )
{
/* Print out the name of this task. */
vPrintString( "Task1 is running\r\n" );
/* 创建任务2为最高优先级。 */
xTaskCreate( vTask2, "Task 2", 1000, NULL, 2, &xTask2Handle ); /* 最后一个参数为任务句柄 */
/* 因为任务2具有最高优先级,所以任务1运行到这里时,任务2已经完成执行,删除了自己。任务1得以
执行,延迟100ms阻塞一段时间 */
vTaskDelay( xDelay100ms ); /*此时任务1进入阻塞状态,空闲任务得到执行机会,空闲任务会释放内核为已删除的任务2分配的内存*/
}
}
任务 1 离开阻塞态后,再一次成为就绪态中具有最高优先级的任务,因此会抢占
空闲任务。又再一次创建任务2,如此往复。
void vTask2( void *pvParameters )
{
/* 任务2什么也没做,只是删除自己。删除自己可以传入NULL值,这里为了演示,还是传入其自己的句柄。 */
vPrintString( "Task2 is running and about to delete itself\r\n" );
vTaskDelete( xTask2Handle );
}
附:FreeRTOS关于vTaskDelete()的源码:
void vTaskDelete( xTaskHandle pxTaskToDelete )
{
tskTCB *pxTCB;
taskENTER_CRITICAL();
{
if( pxTaskToDelete == pxCurrentTCB )
{
pxTaskToDelete = NULL; /*任务通过传入NULL值来删除自己*/
}
pxTCB = prvGetTCBFromHandle( pxTaskToDelete );
vListRemove( &( pxTCB->xGenericListItem ) );/* 将任务从就绪链表中删除 */
if( pxTCB->xEventListItem.pvContainer ) /* 检查任务是否等待任何事件 */
{
vListRemove( &( pxTCB->xEventListItem ) );/* 将任务从事件链表中删除 */
}
/*将任务添加到终止链表中,Idle 任务会将其真正删除(prvCheckTasksWaitingTermination) */
vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
++uxTasksDeleted;/* Idle 任务根据这个变量知道有需要删除的任务 */
/* 通知 kernel aware debuggers 更新任务列表. */
uxTaskNumber++; /* 这里似乎应该是 uxTaskNumber--; */
traceTASK_DELETE( pxTCB );
}
taskEXIT_CRITICAL();
/* 如果删除的是当前任务,则需要任务调度 */
if( xSchedulerRunning != pdFALSE )
{
if( ( void * ) pxTaskToDelete == NULL )
{
portYIELD_WITHIN_API();
}
}
}