您的位置:首页 > 其它

FreeRTOS之任务创建删除

2017-08-25 20:55 525 查看
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链表,如果有任务在这个表上,释放该任务占用的内存空间,并把该任务从任务删除链表中删除。
[align=left]/****************************************************************[/align]
[align=left]**参数:pxTaskToDelete是一个指向被删除任务的句柄,这里其实就是等价于任务控制块[/align]
[align=left]**如果这个句柄==NULL,则表示要删除当前任务[/align]
[align=left]*******************************************************************/[/align]
[align=left]void vTaskDelete( xTaskHandle pxTaskToDelete )[/align]
[align=left]{[/align]
[align=left] tskTCB *pxTCB;[/align]
[align=left] taskENTER_CRITICAL();[/align]
[align=left] {[/align]
[align=left] /* 如果删除的是当前任务,则删除完成后需要进行调度*/[/align]
[align=left] if( pxTaskToDelete == pxCurrentTCB )[/align]
[align=left] {[/align]
[align=left] pxTaskToDelete = NULL;[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] /*通过传进来的任务句柄得到对应的tcb*/[/align]
[align=left] pxTCB = prvGetTCBFromHandle( pxTaskToDelete );[/align]
[align=left] traceTASK_DELETE( pxTCB );[/align]
[align=left] [/align]
[align=left] /* 把任务从就绪链表或者延时链表或者挂起链表中删除*/[/align]
[align=left] vListRemove( &( pxTCB->xGenericListItem ) );[/align]
[align=left] [/align]
[align=left] /* 判断任务是否在等待事件(semaphore消息队列等) */ [/align]
[align=left] if( pxTCB->xEventListItem.pvContainer )[/align]
[align=left] {//如果是,则把它从事件等待链表中删除[/align]
[align=left] vListRemove( &( pxTCB->xEventListItem ) );[/align]
[align=left] }[/align]
[align=left] //插入等待删除链表[/align]
[align=left] vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );[/align]
[align=left] //增加uxTasksDeleted计数[/align]
[align=left] ++uxTasksDeleted;[/align]
[align=left] }[/align]
[align=left] taskEXIT_CRITICAL();[/align]
[align=left] [/align]
[align=left] /*如果调度器已经运行,并且删除的是当前任务,则调度*/[/align]
[align=left] if( xSchedulerRunning != pdFALSE )[/align]
[align=left] {[/align]
[align=left] if( ( void * ) pxTaskToDelete == NULL )[/align]
[align=left] {[/align]
[align=left] taskYIELD();[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]再看空闲任务做的第2步工作:[/align]
[align=left]static portTASK_FUNCTION( prvIdleTask, pvParameters )[/align]
[align=left]{[/align]
[align=left] /* Stop warnings. */[/align]
[align=left] ( void ) pvParameters;[/align]
[align=left] [/align]
[align=left] for( ;; )[/align]
[align=left] {[/align]
[align=left] /* See if any tasks have been deleted. */[/align]
[align=left] prvCheckTasksWaitingTermination();[/align]
[align=left] …………………………….÷[/align]
[align=left]* The portTASK_FUNCTION() macro is used to allow port/compiler specific[/align]
[align=left] * language extensions. The equivalent prototype for this function is:[/align]
[align=left] * void prvIdleTask( void *pvParameters );[/align]
[align=left]这里prvCheckTasksWaitingTermination()就是干这第2步的工作:每次调用它删除一个任务[/align]
[align=left]static void prvCheckTasksWaitingTermination( void )[/align]
[align=left]{ [/align]
[align=left] #if ( INCLUDE_vTaskDelete == 1 )[/align]
[align=left] { [/align]
[align=left] portBASE_TYPE xListIsEmpty;[/align]
[align=left] [/align]
[align=left] /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called[/align]
[align=left] too often in the idle task. */[/align]
[align=left] if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 )[/align]
[align=left] {//禁止调度[/align]
[align=left] vTaskSuspendAll();[/align]
[align=left] //打开调度[/align]
[align=left] xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );[/align]
[align=left] xTaskResumeAll();[/align]
[align=left] [/align]
[align=left] if( !xListIsEmpty )[/align]
[align=left] {[/align]
[align=left] tskTCB *pxTCB;[/align]
[align=left] //关中断[/align]
[align=left] portENTER_CRITICAL();[/align]
[align=left] { [/align]
[align=left] pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) );[/align]
[align=left] vListRemove( &( pxTCB->xGenericListItem ) );[/align]
[align=left] --uxCurrentNumberOfTasks;[/align]
[align=left] --uxTasksDeleted;[/align]
[align=left] }[/align]
[align=left] portEXIT_CRITICAL();[/align]
[align=left] //释放内存,删除tcb[/align]
[align=left] prvDeleteTCB( pxTCB );[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] #endif[/align]
[align=left]} [/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: