FreeRTOS源码分析-2任务挂起和恢复

文章详细介绍了嵌入式实时操作系统中任务挂起和恢复的业务流程。挂起任务包括从就绪列表和事件列表中删除任务,然后将其添加到挂起列表;恢复任务则涉及从挂起列表移除任务并将其添加回就绪列表。过程中涉及到临界段保护、任务控制块操作以及调度器的状态管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1 任务挂起

2 任务恢复


1 任务挂起

任务挂起与任务删除类似

任务挂起业务流程:

  • 从就绪列表中删除
  • 从事件列表中删除
  • 添加任务到挂起列表中
  • 开始任务调度

源码分析

void vTaskSuspend( TaskHandle_t xTaskToSuspend )
{
    TCB_t *pxTCB;

    //进入临界段----原理之后会讲
	taskENTER_CRITICAL();
	{
		/* 获取任务控制块 */
		pxTCB = prvGetTCBFromHandle( xTaskToSuspend );

        //trace是用户自己实现,不用分析
		traceTASK_SUSPEND( pxTCB );

		/*从就绪列表中移除*/
		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 )
		{
			/*如果是当前任务,立即开启任务调度,释放CPU */
			configASSERT( uxSchedulerSuspended == 0 );
			portYIELD_WITHIN_API();
		}
		else
		{
			/*如果调度器没开启,读取当前任务挂起列表的长度
              长度相同代表:如果已经把所有任务挂起
            */
			if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
			{
				/* 那么把当前任务的控制块赋值未NULL,不让任务控制块再使用 */
				pxCurrentTCB = NULL;
			}  //如果还有任务在就绪列表
			else 
			{
                //任务上下文切换----后面再讲解
                //即再就绪列表中找到优先级最高的任务,进行调度
				vTaskSwitchContext();
			}
		}
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
}

2 任务恢复

任务恢复业务流程:

  • 从挂起列表中删除
  • 添加任务到就绪列表
  • 开启任务调度
void vTaskResume( TaskHandle_t xTaskToResume )
{
    //获取需要恢复的任务控制块
    TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;

	/*参数检查 */
	configASSERT( xTaskToResume );

	/*指针不为空且不是当前任务控制块
        既然要使用任务控制块肯定不为空
        既然要恢复,肯定不能当前的执行任务
     */
	if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
	{
        //进入临界段
		taskENTER_CRITICAL();
		{
            //判断任务是否已经挂起,必须挂起才能恢复
			if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
			{
                //自己实现的函数,不分析
				traceTASK_RESUME( pxTCB );

				/*从挂起列表中移除,就绪任务、挂起任务等都在statelist列表中 */
				( void ) uxListRemove(  &( pxTCB->xStateListItem ) );
                //添加任务到就绪列表
				prvAddTaskToReadyList( pxTCB );

				/* 判断要恢复的任务,是否大于当前任务优先级
                    前提条件:已经使能了抢占式调度器
                */
				if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
				{
					/* 释放CPU的使用权,开始内核调度 */
					taskYIELD_IF_USING_PREEMPTION();
				}
				else 
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
        //退出临界段
		taskEXIT_CRITICAL();
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}
}

另外有在中断中恢复任务函数:因为有调度,这是不允许的,所以有特殊的在中断中调度的任务函数 xTaskResumeFromISR

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

4IOT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值