(一)任務刪除函數詳解 直接上代碼! void vTaskDelete( TaskHandle_t xTaskToDelete ){ TCB_t *pxTCB; taskENTER_CRITICAL(); { /* 獲取要刪除任務的任務控制塊,參數是任務句柄,如果參數為當前正在執行的任務句柄,那麼返 ...
(一)任務刪除函數詳解
vTaskDelete()函數用於刪除一個任務,形參為要刪除任務的任務句柄,如果刪除自身,那麼參數為NULL。要想使用該函數,必須將巨集INCLUDE_vTaskDelete定義為1;要刪除的任務就是把任務從所有就緒列表,阻塞列表,掛起列表中刪除。
直接上代碼!
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(); } } }
具體的結構框圖如下所示:
(二)任務掛起函數詳解
vTaskSuspend()函數用於掛起指定的任務,被掛起的任務失去cpu的使用權,不管是什麼優先順序。可以將任何狀態的任務掛起。要用此函數,INCLUDE_vTaskDelete必須定義為1。
直接上代碼!
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(); } }
首先要保證要恢復的任務不能是空並且不能是當前正在運行的任務,不然不需要恢復了,然後看下麵的結構圖,比對著代碼就行了。
好!本章就先介紹到這裡,下章介紹開啟任務調度!