FreeRTOS数据结构(一)-链表和链表项

结构体定义

/*链表结构体*/
typedef struct xLIST
{
    listFIRST_LIST_INTEGRITY_CHECK_VALUE  /*用于链表完整性检查*/
    configLIST_VOLATILE UBaseType_t uxNumberOfItems; /*记录链表项数目*/
    ListItem_t * configLIST_VOLATILE pxIndex; /*用于遍历链表,初始化会指向最后的链表项,这里需要注意使用了volatile关键字,表明该指针可能会在其他地方修改*/
    MiniListItem_t xListEnd;/*用于标记链表尾*/
    listSECOND_LIST_INTEGRITY_CHECK_VALUE /*用于链表完整性检查*/
} List_t;
/*链表项结构体*/
struct xLIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*用于链表完整性检查*/
    configLIST_VOLATILE TickType_t xItemValue;/*链表项值:大部分时候根据此值升序排列*/
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;/*指向下一个节点*/
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;/*指向上一个节点*/  
    void * pvOwner; /*指向结构体控制块*/
    void * configLIST_VOLATILE pvContainer;/*指向该链表项对应的链表*/
    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*用于链表完整性检查*/    
};
/*迷你链表项结构体*/
struct xMINI_LIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
    configLIST_VOLATILE TickType_t xItemValue;
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};

根据定义可以看出以下几点:

  1. 链表结构是一个双向链表。
  2. 每个链表都由链表和链表项组成。
  3. 链表结构体本身有一个迷你链表项,用来标记链表的结尾。

链表和链表项初始化

/*链表初始化*/
void vListInitialise( List_t * const pxList )
{
    /*将链表的Index索引指针指向自身的迷你链表项,即链表结尾*/
    pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );           
    /*将迷你链表项值设置为最大值,确保处于链表结尾*/
    pxList->xListEnd.xItemValue = portMAX_DELAY;
    /*由于链表中没有节点,链表尾节点的下一项和上一项都是自身,表明这是一个循环链表*/
    pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
    pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
    pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
    /*初始化链表的完整性检查值*/
    listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
    listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
/*链表项初始化*/
void vListInitialiseItem( ListItem_t * const pxItem )
{
    /*确保该链表项没有被链表使用,往往初始化链表项之后就会进行插入或设置操作*/
    pxItem->pvContainer = NULL;
    /*初始化完整性检查*/
    listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
    listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}

链表的操作

链表的插入会根据List Item Value进行升序排列,其他并没有什么特殊的地方。初始化并插入两个节点后大概的数据结构,如下图所示:
FreeRTOS数据结构(一)-链表和链表项_第1张图片

从图中可以看出,List初始化并添加节点后,List Item 1/List Item 2 和 List自己的xListEnd节点一起组成了一个双向循环的链表。

Q&A

1).如何完成链表的完整性检查?
如果打开了完整性检查的开关(configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES),每个链表和链表项结构都会定义listFIRST_LIST_INTEGRITY_CHECK_VALUElistSECOND_LIST_INTEGRITY_CHECK_VALUE(mini链表项没有定义这个),该定义是一个16位或32位的整形数,在链表或链表项初始化的时候会将该变量初始化为0x5a5a或0x5a5a5a5a,在检查的时候如果这两个变量都没有改变则通过完整性检查,否则认为链表被破坏。

2).如何使用List?

  1. 必须先定义一个List_t的全局变量,比如Timer中的 xActiveTimerList1
  2. 每一个节点结构体必须包含xLIST_ITEM类型的成员。
  3. 初始化链表后,将含有List Item成员的数据结构按照链表项值的大小插入到链表中,比如Timer中利用该值溢出的判断。
  4. 设置好pvOwner指针,后续可以根据该指针反向找到该节点的具体结构,如Timer_t。

你可能感兴趣的:(FreeRTOS)