2. FreeRTOS系统中任务的状态与列表项

第一节 前言

        FreeRTOS 在学习完FreeRTOS的创建与删除后,下一步需要学习在项目的整个运行过程中,任务处于哪一种状态。FreeRTOS 中的任务永远处于下面四个状态,运行态、就绪态、阻塞态、挂起态。任务在四个状态中转换,只有处于运行态的任务才是当前进程中正在运行的任务。下面是对四种状态的学习。

第二节 任务的状态

        个人觉得,在开始学习阶段不需要花费过多的时间学习其中状态的转换过程,只需要理解处于每个状态的任务在整个项目运行过程中的参与情况。

a.运行态

        当一个任务正在运行时, 该任务则处于运行态, 处于运行态的任务就是当前正在使用处理器的任务。 处于运行态的任务一定是就绪链表中优先级最高的任务(所以运行态的任务本质是从就绪链表中取出的优先级最高的任务)。对于单核处理器来说,不管在任何时刻FreeRTOS同一时刻只能有一个任务在运行态。

b.就绪态

        处于就绪态的任务是那些已经准备就绪(即没有被阻塞或者挂起), 已具备执行的能力可以随时准备运行的任务,等待调度器进行调度,新创建的任务会直接初始化为就绪态

c.阻塞态

        一个任务进入阻塞态有两种情况,一个任务当前正在等待某个外部事件的话就说它处于阻塞态(任务需要等待队列、信号量、事件组、通知或互斥信号量),或者任务因为某个超时时间而处于阻塞态(某个任务调用了函数 vTaskDelay())。进入阻塞态的任务从就绪链表中移除,任务被添加至延时链表/等待事件上的链表。

d.挂起态

        任务进入挂起态后不能被调度器调用进入运行态。挂起的任务会被挂入悬起链表中,表示任务已暂停,让一个任务进入挂起状态的唯一办法就是调用vTaskSuspend()函数,而 把 一 个 挂 起 状态 的FreeRTOS任 务 恢复的 唯 一 途 径 就 是 调用vTaskResume() 或 vTaskResumeFromISR()函数,在挂起态的任务永远不可能参与调度。

第三节 列表(链表)

         FreeRTOS中调度大量使用了列表(list)和列表项(list item)数据结构,任务的四种状态就是使用列表来表示的。

1. 列表项

        下面是列表项结构体,只介绍使用列表项中所用到的元素,可以把列表项直接当作链表来看待。列表项服务与任务,每一个任务都会有对应的自身的列表项。

struct xLIST_ITEM
{
     configLIST_VOLATILE TickType_t xItemValue;           /*列表项值*/
     struct xLIST_ITEM * configLIST_VOLATILE pxNext;      /*指向列表中下一个列表项*/
     struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;  /*指向列表中上一个列表项*/
     void * pvOwner;                                     /*指向拥有该列表项对应任务的TCB*/
     void * configLIST_VOLATILE pvContainer;             /*指向包含该列表项的列表 */
};
typedef struct xLIST_ITEM ListItem_t;

        在使用xTaskCreate创建任务时,会初始化一个任务控制块结构体。下面是对TCB的常用的元素的中会使用列表项。

typedef tskTCB TCB_t;

typedef struct tskTaskControlBlock
{
    volatile StackType_t    *pxTopOfStack;    //位于TCB第一项的栈顶指针,便于对任务控制块TCB进行操作

    ListItem_t            xStateListItem;    //任务状态列表项,对于任务处于四种状态之一的挂接
    ListItem_t            xEventListItem;   //事件列表项
    UBaseType_t            uxPriority;     //任务优先级,数值越大优先级越高
    StackType_t            *pxStack;       //指向堆栈的起始位置
    char                pcTaskName[ configMAX_TASK_NAME_LEN ];  //任务名字

    .......   .......                                     //结构体中的内容后续再做分析

} tskTCB;

2. 列表项的初始化

a.初始化列表项的调用过程如下:

xTaskCreate()                        //创建任务

-> prvInitialiseNewTask()       // 初始化任务,对TCB中的各字段初始化

- >vListInitialiseItem( &( pxNewTCB->xStateListItem ) )       //列表项初始化

->listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB )  //设置列表项的pvOwner

b.将任务添加到就绪列表中

prvAddNewTaskToReadyList( pxNewTCB ) ->prvAddTaskToReadyList( pxNewTCB )

在task.c中已经定义了全局变量pxReadyTasksLists[]作为就绪列表

PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];

其他的状态列表在Study任务调度器时再进行分析。

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值