(一)任務洗掉函式詳解
直接上代碼!
void vTaskDelete( TaskHandle_t xTaskToDelete ){ TCB_t *pxTCB; taskENTER_CRITICAL(); { /* 獲取要洗掉任務的任務控制塊,引數是任務句柄,如果引數為當前正在執行的任務句柄,那么回傳值為null */ pxTCB = prvGetTCBFromHandle( xTaskToDelete ); /* 將任務從就緒串列中洗掉 */ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ){ taskRESET_READY_PRIORITY( pxTCB->uxPriority ); } else{ mtCOVERAGE_TEST_MARKER(); } /* 查看任務是否在等待某個事件信號量,佇列等,并將其從相應的列中洗掉 */ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ){ ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); } else{ mtCOVERAGE_TEST_MARKER(); } uxTaskNumber++; /* 如果要洗掉的是當前正在運行的任務 */ if( pxTCB == pxCurrentTCB ){ /* 把任務添加到等待洗掉的任務串列中,并在空閑任務中洗掉 */ vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) ); /* 記錄有多少個任務需要釋放記憶體 */ ++uxDeletedTasksWaitingCleanUp; /* 任務洗掉鉤子函式---需要用戶自己實作*/ portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending ); } else{ /* 要洗掉的是別的任務 */ --uxCurrentNumberOfTasks; prvDeleteTCB( pxTCB ); /* 重新計算還要多長時間執行下一個任務 */ prvResetNextTaskUnblockTime(); } traceTASK_DELETE( pxTCB ); } /* 退出臨界段 */ taskEXIT_CRITICAL(); /* 如果任務調度器開啟 */ if( xSchedulerRunning != pdFALSE ){ /* 如果是洗掉任務本身,馬上進行任務調度)*/ if( pxTCB == pxCurrentTCB ){ configASSERT( uxSchedulerSuspended == 0 ); portYIELD_WITHIN_API(); } else{ mtCOVERAGE_TEST_MARKER(); } } }
具體的結構框圖如下所示:

(二)任務掛起函式詳解
直接上代碼!
void vTaskSuspend(TaskHandle_t xTaskToSuspend){ TCB_t *pxTCB; taskENTER_CRITICAL(); { /* 獲取任務控制塊,若為NULL則掛起自身 */ pxTCB = prvGetTCBFromHandle(xTaskToSuspend); /* 將任務從就緒串列、阻塞串列等中移除 */ if(uxListRemove(&(pxTCB->xStateListItem)) == (UBaseType_t)0){ taskRESET_READY_PRIORITY(pxTCB->uxPriority); } else{ mtCOVERAGE_TEST_MARKER(); } /* 查看任務是否在等待某個事件,如是則將其從事件串列中移除 */ if(listLIST_ITEM_CONTAINER(&(pxTCB->xEventListItem))!=NULL){ (void) uxListRemove(&(pxTCB->xEventListItem)); } else{ mtCOVERAGE_TEST_MARKER(); } /* 將任務添加到掛起任務串列表尾 */ vListInsertEnd(&xSuspendedTaskList, &(pxTCB->xStateListItem)); } taskEXIT_CRITICAL(); if(xSchedulerRunning != pdFALSE){ //如果任務調度器開啟 /* 重新計算還要多長時間執行下一個任務 */ taskENTER_CRITICAL(); { prvResetNextTaskUnblockTime(); } taskEXIT_CRITICAL(); } else{ mtCOVERAGE_TEST_MARKER(); } if(pxTCB == pxCurrentTCB){ if(xSchedulerRunning != pdFALSE){ /* 若剛掛起的是正在運行的任務,且任務調度器運行正常,則強制進行一次任務切換 */ configASSERT( uxSchedulerSuspended == 0 ); portYIELD_WITHIN_API(); } else{ /* 若任務調度器沒有開啟,則讀取當前任務掛起串列的長度,判斷所有任務是否都被掛起*/ if(listCURRENT_LIST_LENGTH(&xSuspendedTaskList) == uxCurrentNumberOfTasks){ /* 若所有任務都被掛起,把當前的任務控制塊賦值為NULL */ pxCurrentTCB = NULL; } else{ /* 若還有沒被掛起的任務,則獲取下一個要運行的任務 */ vTaskSwitchContext(); } } } else{ mtCOVERAGE_TEST_MARKER(); } }
可見任務掛起和任務洗掉函式有許多共同之處,
結構圖如下,仔細分析哦

(三)任務恢復函式詳解
直接上代碼!
void vTaskResume(TaskHandle_t xTaskToResume){ /* 獲取要恢復的任務控制塊 */ TCB_t * const pxTCB = (TCB_t *) xTaskToResume; configASSERT( xTaskToResume ); /* 任務控制塊不能為NULL和當前任務 */ if(( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB )){ taskENTER_CRITICAL(); { /* 判斷要恢復的任務是否已經被掛起 */ if(prvTaskIsTaskSuspended(pxTCB) != pdFALSE){ /* 從掛起串列中移除 */ (void) uxListRemove(&( pxTCB->xStateListItem)); /* 添加到就緒串列中 */ prvAddTaskToReadyList( pxTCB ); /* 要恢復的任務優先級高于當前正在運行的任務優先級 */ if(pxTCB->uxPriority >= pxCurrentTCB->uxPriority){ /* 完成一次任務切換 */ taskYIELD_IF_USING_PREEMPTION(); } else{ mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL(); } else{ mtCOVERAGE_TEST_MARKER(); } }
首先要保證要恢復的任務不能是空并且不能是當前正在運行的任務,不然不需要恢復了,然后看下面的結構圖,比對著代碼就行了,

好!本章就先介紹到這里,下章介紹任務切換!
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/456065.html
標籤:嵌入式
