当前位置: 首页 > news >正文

种子汤唯梁朝伟做视频网站北京网站优化培训

种子汤唯梁朝伟做视频网站,北京网站优化培训,最简约的网站,国外优秀电商设计网站前言 本文在前面文章的基础上实现了延时列表,取消了 TCB 中的延时参数。 本文是对野火 RTOS 教程的笔记,融入了笔者的理解,代码大部分来自野火。 一、如何更高效地查找延时到期的任务 1. 朴素方式 在本文之前,我们使用了一种朴…

前言

本文在前面文章的基础上实现了延时列表,取消了 TCB 中的延时参数。
本文是对野火 RTOS 教程的笔记,融入了笔者的理解,代码大部分来自野火。

一、如何更高效地查找延时到期的任务

1. 朴素方式

  • 在本文之前,我们使用了一种朴素的思想进行延时任务的查找:
    • 在 TCB 中设置一个延时参数,需要延时的时候进行初始化
    • 将延时任务挂起(清除就绪优先级位 uxTopReadyPriority)
    • 当 SysTick 中断时,扫描就绪列表中每个 TCB,如果延时参数不为 0 就减 1
    • 如果延时参数被减到 0,就置对应的就绪优先级位 uxTopReadyPriority,然后进行任务切换
      可以看到,上面这种想法非常朴素,但是每次 SysTick 中断的时候都需要扫描一遍就绪列表中的所有任务,当任务多的时候,耗时将会很多。

2. 更高效的方式

  • 设置除就绪列表外的另一个列表——延时列表
  • 当任务要进入延时的时候,将延时到期的值设置为节点的排序值,根据排序值按升序插入延时列表中,然后将该任务从就绪列表中删除
  • 同时更新下一个任务的解锁时刻的变量 xNextTaskUnblockTime,这个变量的意思是,当系统时基计数器 xTickCount 的值与 xNextTaskUnblockTime 相等时,就表示有任务延时到期了,需要将该任务就绪
    可以看到,FreeRTOS 用这种方式避免了扫描所有任务的延时,这点是优于 RT-Thread 和 μC/OS 的。

实际上,有两个延时列表,这是为了解决延时时间溢出的问题。

如图:
在这里插入图片描述

二、代码详解

我们添加或修改以下的代码:

  • 两条延时列表的定义和初始化
  • 下一任务到期时间点变量的定义及初始化
  • 修改延时函数,延时时将任务从就绪列表中删除并添加到延时列表
  • 修改时基计数器中断,每次计时时查看是否有任务到期

还有一些辅助的函数,主要是解决当计时溢出或者延时溢出时两条延时列表的切换:

  • 切换当前延时列表指针和溢出延时列表指针函数
  • 更新任务到期时间点变量的函数

1. 延时列表的定义及初始化

① 定义

  • 定义了两个任务延时列表,当系统时基计数器xTickCount 没有溢出时,用一条列表,当 xTickCount 溢出后,用另外一条列表
  • pxDelayedTaskList 指向 xTickCount 没有溢出时使用的那条列表
  • pxOverflowDelayedTaskList 指向 xTickCount 溢出时使用的那条列表
//延时列表
static List_t xDelayedTaskList1;
static List_t xDelayedTaskList2;
//延时列表指针(用于切换)
static List_t * volatile pxDelayedTaskList;
static List_t * volatile pxOverflowDelayedTaskList;

② 初始化

/* 初始化任务相关的列表 */
void prvInitialiseTaskLists( void )
{UBaseType_t uxPriority;//就绪列表初始化for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ){vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );	//初始化每个就绪列表}//延时列表初始化vListInitialise( &xDelayedTaskList1 );vListInitialise( &xDelayedTaskList2 );pxDelayedTaskList = &xDelayedTaskList1;pxOverflowDelayedTaskList = &xDelayedTaskList2;
}

2. 下一任务到期时间点变量的定义和初始化

  • xNextTaskUnblockTime 用于表示下一个任务的解锁时刻
  • xNextTaskUnblockTime = xTickCount + xTicksToDelay(当前时间 + 延时时间)
  • 当系统时基计数器 xTickCount 的值与 xNextTaskUnblockTime 相等时,就表示有任务延时到期了,需要将该任务就绪

① 定义

//下一个延时任务到期的时间
static volatile TickType_t xNextTaskUnblockTime		= ( TickType_t ) 0U;

② 初始化

  • 在 vTaskStartScheduler 任务调度器函数中初始化为 portMAX_DELAY
  • portMAX_DELAY 是一个 portmacro.h 中定义的宏,默认为 0xffffffffUL
#define portMAX_DELAY ( TickType_t ) 0xffffffffULvoid vTaskStartScheduler( void )
{
/*======================================创建空闲任务start==============================================*/     TCB_t *pxIdleTaskTCBBuffer = NULL;StackType_t *pxIdleTaskStackBuffer = NULL;uint32_t ulIdleTaskStackSize;/* 获取空闲任务的内存:任务栈和任务TCB */vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );    xIdleTaskHandle = xTaskCreateStatic( (TaskFunction_t)prvIdleTask,              /* 任务入口 */(char *)"IDLE",                           /* 任务名称,字符串形式 */(uint32_t)ulIdleTaskStackSize ,           /* 任务栈大小,单位为字 */(void *) NULL,                            /* 任务形参 */(UBaseType_t) tskIDLE_PRIORITY,           /* 任务优先级,数值越大,优先级越高 */(StackType_t *)pxIdleTaskStackBuffer,     /* 任务栈起始地址 */(TCB_t *)pxIdleTaskTCBBuffer );           /* 任务控制块 */
/*======================================创建空闲任务end================================================*/ xNextTaskUnblockTime = portMAX_DELAY;xTickCount = ( TickType_t ) 0U;/* 启动调度器 */if( xPortStartScheduler() != pdFALSE ){/* 调度器启动成功,则不会返回,即不会来到这里 */}
}

3. 延时函数的修改

任务调用延时函数时,将任务从就绪列表中转移到延时列表中:

void vTaskDelay( const TickType_t xTicksToDelay )
{TCB_t *pxTCB = NULL;/* 获取当前任务的TCB */pxTCB = pxCurrentTCB;/* 将任务插入到延时列表 */prvAddCurrentTaskToDelayedList( xTicksToDelay );/* 任务切换 */taskYIELD();
}
  • 任务插入延时列表使用 prvAddCurrentTaskToDelayedList()
  • 这个函数除了插入操作还处理了延时溢出的情况
  • 笔者画了个流程图方便大家理解:
    在这里插入图片描述
//将任务插入到延时列表
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait )
{TickType_t xTimeToWake;/* 获取系统时基计数器xTickCount的值 */const TickType_t xConstTickCount = xTickCount;/* 将任务从就绪列表中移除 */if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ){/* 将任务在优先级位图中对应的位清除 */portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );}/* 计算延时到期时,系统时基计数器xTickCount的值是多少 */xTimeToWake = xConstTickCount + xTicksToWait;/* 将延时到期的值设置为节点的排序值 */listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );/* 溢出 */if( xTimeToWake < xConstTickCount ){vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );}else /* 没有溢出 */{vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );/* 更新下一个任务解锁时刻变量xNextTaskUnblockTime的值 */if( xTimeToWake < xNextTaskUnblockTime ){xNextTaskUnblockTime = xTimeToWake;}}	
}

4. 修改时基计数器中断

  • 修改时基计数器中断,每次计时时查看是否有任务到期
  • 并且处理时基计数器溢出情况
  • 函数流程图如下
    在这里插入图片描述
  • 函数代码如下:
//系统时基计数
void xTaskIncrementTick( void )
{TCB_t * pxTCB;TickType_t xItemValue;//系统时基计数 + 1const TickType_t xConstTickCount = xTickCount + 1;xTickCount = xConstTickCount;/* 如果xConstTickCount溢出,则切换延时列表 */if( xConstTickCount == ( TickType_t ) 0U ){taskSWITCH_DELAYED_LISTS();}/* 最近的延时任务延时到期 */if( xConstTickCount >= xNextTaskUnblockTime ){for( ;; ){if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ){/* 延时列表为空,设置xNextTaskUnblockTime为可能的最大值 */xNextTaskUnblockTime = portMAX_DELAY;break;}else /* 延时列表不为空 */{pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );/* 直到将延时列表中所有延时到期的任务移除才跳出for循环 */if( xConstTickCount < xItemValue ){xNextTaskUnblockTime = xItemValue;break;}/* 将任务从延时列表移除,消除等待状态 */( void ) uxListRemove( &( pxTCB->xStateListItem ) );/* 将解除等待的任务添加到就绪列表 */prvAddTaskToReadyList( pxTCB );}}}/* xConstTickCount >= xNextTaskUnblockTime *//* 任务切换 */portYIELD();
}

5. 交换非溢出延时指针和溢出延时指针

  • 使用一个中间变量进行交换
  • 切换延时列表后记得更新 xNextTaskUnblockTime 的值
/* * 当系统时基计数器溢出的时候,延时列表pxDelayedTaskList 和* pxOverflowDelayedTaskList要互相切换*/
#define taskSWITCH_DELAYED_LISTS()\
{\List_t *pxTemp;\pxTemp = pxDelayedTaskList;\pxDelayedTaskList = pxOverflowDelayedTaskList;\pxOverflowDelayedTaskList = pxTemp;\xNumOfOverflows++;\prvResetNextTaskUnblockTime();\
}

6. 更新任务到期时间点变量的函数

  • 函数流程图:
    在这里插入图片描述

  • 函数代码:

//重新设置变量xNextTaskUnblockTime的值
static void prvResetNextTaskUnblockTime( void )
{TCB_t *pxTCB; // 定义一个指向TCB_t类型的指针变量pxTCBif( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ){/* 新的延时任务列表为空。将xNextTaskUnblockTime设置为最大可能值,以确保在延时列表中有任务项之前,if( xTickCount >= xNextTaskUnblockTime )的测试不会通过。 */xNextTaskUnblockTime = portMAX_DELAY;}else{/* 新的延时任务列表不为空,获取延时列表头部任务的值。这个值表示了延时列表头部任务应该从阻塞状态中解除的时间。 */( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );}
}

后记

如果您觉得本文写得不错,可以点个赞激励一下作者!
如果您发现本文的问题,欢迎在评论区或者私信共同探讨!
共勉!


文章转载自:
http://dinncosubcutaneously.knnc.cn
http://dinncotrijugous.knnc.cn
http://dinncofecundity.knnc.cn
http://dinncoyarraman.knnc.cn
http://dinncoclarinet.knnc.cn
http://dinncokonimeter.knnc.cn
http://dinncocabotage.knnc.cn
http://dinncochuckawalla.knnc.cn
http://dinncoachillean.knnc.cn
http://dinncoeviscerate.knnc.cn
http://dinncosouthron.knnc.cn
http://dinncolumumbist.knnc.cn
http://dinncopronate.knnc.cn
http://dinncothinkpad.knnc.cn
http://dinncorakata.knnc.cn
http://dinncofebricula.knnc.cn
http://dinncogalligaskins.knnc.cn
http://dinncoreproachingly.knnc.cn
http://dinncofootscraper.knnc.cn
http://dinncosorbitol.knnc.cn
http://dinncobms.knnc.cn
http://dinncogill.knnc.cn
http://dinncophotoengraving.knnc.cn
http://dinncoblackish.knnc.cn
http://dinncovillanage.knnc.cn
http://dinncoposterior.knnc.cn
http://dinncoecotype.knnc.cn
http://dinncomicrocircuit.knnc.cn
http://dinncoblockboard.knnc.cn
http://dinncopoetical.knnc.cn
http://dinncocrampon.knnc.cn
http://dinncolathwork.knnc.cn
http://dinncoadmissibility.knnc.cn
http://dinncointerindividual.knnc.cn
http://dinncobetrayer.knnc.cn
http://dinncosienna.knnc.cn
http://dinncorwandan.knnc.cn
http://dinncoshears.knnc.cn
http://dinncoconrad.knnc.cn
http://dinncoiridium.knnc.cn
http://dinncozooid.knnc.cn
http://dinncolecithality.knnc.cn
http://dinncoodontophore.knnc.cn
http://dinncoinbreathe.knnc.cn
http://dinncovaccinee.knnc.cn
http://dinncoindoor.knnc.cn
http://dinncoobvert.knnc.cn
http://dinncocheckrow.knnc.cn
http://dinncotoadyism.knnc.cn
http://dinncoantidote.knnc.cn
http://dinncoworrit.knnc.cn
http://dinncomillicurie.knnc.cn
http://dinncoturd.knnc.cn
http://dinncoepulis.knnc.cn
http://dinncogooral.knnc.cn
http://dinncobroker.knnc.cn
http://dinncofayalite.knnc.cn
http://dinncodefendant.knnc.cn
http://dinncoagrarian.knnc.cn
http://dinncodiscreteness.knnc.cn
http://dinncofluviology.knnc.cn
http://dinncophosphatidylcholine.knnc.cn
http://dinncocloak.knnc.cn
http://dinncobolshy.knnc.cn
http://dinncoshocked.knnc.cn
http://dinncomaidless.knnc.cn
http://dinncohypogamy.knnc.cn
http://dinncodysautonomia.knnc.cn
http://dinncopolymerase.knnc.cn
http://dinncobantingism.knnc.cn
http://dinncoviolator.knnc.cn
http://dinncosiberian.knnc.cn
http://dinncofitment.knnc.cn
http://dinncodesiccated.knnc.cn
http://dinncographitoid.knnc.cn
http://dinncomilden.knnc.cn
http://dinncodisseminate.knnc.cn
http://dinncomerl.knnc.cn
http://dinncosoapboxer.knnc.cn
http://dinncocongratters.knnc.cn
http://dinncoswoop.knnc.cn
http://dinncoliterally.knnc.cn
http://dinnconewfangled.knnc.cn
http://dinncocrew.knnc.cn
http://dinncochiastolite.knnc.cn
http://dinncoelectrification.knnc.cn
http://dinncohyperspatial.knnc.cn
http://dinncosemasiology.knnc.cn
http://dinncojargonelle.knnc.cn
http://dinncofaldstool.knnc.cn
http://dinncoaffluency.knnc.cn
http://dinncosecretaryship.knnc.cn
http://dinncophraseman.knnc.cn
http://dinncohyracoid.knnc.cn
http://dinncoalsatia.knnc.cn
http://dinncoprelim.knnc.cn
http://dinncowaffie.knnc.cn
http://dinncosatelloid.knnc.cn
http://dinnconordic.knnc.cn
http://dinncodephlegmate.knnc.cn
http://www.dinnco.com/news/99577.html

相关文章:

  • 上海服装品牌网站建设推广普通话内容100字
  • 河北省网站建设公司排名苏州网站建设哪家靠谱
  • 公司怎么开网站关键词优化是什么意思
  • 宜兴网站建设百度怎么做广告推广
  • 嘉兴网站推广优化公司百度热度
  • 长春市做网站的公司seo全网营销公司
  • 微网站建设比较全面的是seo网站分析报告
  • 怎么去掉网站底部信息网站seo排名免费咨询
  • 企业网站栏目结构头条关键词排名查询
  • wordpress 条件筛选seo com
  • 做网站接私活价格怎么算百度知道首页
  • ps做网站的视频东莞网站建设推广品众
  • 电商网站规划书大数据营销成功案例
  • 怎么用服务器做局域网网站seo排名公司
  • 容易做的网站网站怎么做的
  • 网站建设的报价为什么不同网络服务包括
  • 减肥药可以做网站吗关键词排名点击软件怎样
  • 网站接口需求域名检测
  • 微网站做的比较好的深圳网络营销
  • 房屋中介做网站的网络推广网址
  • 做网站做企业网络营销推广方案策划
  • 营业执照注册官网自助优化排名工具
  • 如何做美女图片网站济南百度代理
  • 河北省石家庄市官网网站怎么优化排名靠前
  • 外贸信托是哪个贷款平台网站seo推广哪家值得信赖
  • 响应网站怎么做教学视频百度如何快速收录网站
  • 做优惠券网站要多少钱seo软件工具
  • 鄞州区住房和城乡建设局网站企业网络组建方案
  • 企业网站上的二维码怎么获得360收录提交
  • 怎样做聊天网站网站应该如何推广