概述
列表与列表项是FreeRTOS中重要的一部分,它可以反映任务中的一些基本信息。
列表的理解比较难,尤其是在列表和列表项进行一个相互指向时会比较难,我这里会详细讲解。
列表的全部东西都是在list.c 和 list.h 中,其实列表也是一种数据结构,它与链表相似,但又比链表拥有更多的内容,我们通过与链表的对比来对列表和列表项进行一个了解。
在list.h 中定义了一个结构体用来记录列表
列表
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE //用来检查链表完整性
configLIST_VOLATILE UBaseType_t uxNumberOfItems; //记录列表中列表项的数量
ListItem_t * configLIST_VOLATILE pxIndex; //指向列表项,用于遍历列表
MiniListItem_t xListEnd; //这是来表示列表结束用的,指向迷你列表项
listSECOND_LIST_INTEGRITY_CHECK_VALUE //用来检查链表完整性
} List_t;
其实列表与链表最主要一个相同点是:当创建一个列表或者链表时,他们都只有一个结点,只不过列表的结点是它本身,这是关于列表的图,1和5对列表的使用关系不大,只是初始化时需要,所以只展示三个。
遍历是怎么用的呢?我们会发现有一个指针pxIndex这个指针就是专门用来遍历的,它会不断的指向下一个列表项。
列表项与迷你列表项
列表项也相当于一个列表的结点,在list.h中也有一个结构体是关于列表项的。
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 //用来检查列表完整性
};
typedef struct xLIST_ITEM ListItem_t;
这里是列表项的图
列表项介绍完了以后我们来介绍迷你列表项,这时有些人会疑惑,为什么有了列表项了还会有迷你列表项呢?其实在某些情况下,比方说尾结点就不需要放一个列表项,放了只会浪费空间,所以我们只需要放一个迷你列表项即可。
struct xMINI_LIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE (1)
configLIST_VOLATILE TickType_t xItemValue; (2)
struct xLIST_ITEM * configLIST_VOLATILE pxNext; (3)
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; (4)
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
其内容与列表项相同,在这里不做解释。
列表初始化和列表项初始化
列表初始化使用一个函数vListInitialise(),以下函数我们只需要看着参考手册即可,在这里只说一下大致初始化的方法,它其实最主要的一步就是让xListEnd当列表的尾部,让xListEnd成为下一个列表项,就是初始化xListEnd的pxNext,因为初始化时一个列表项,所以它指向本身。
列表项初始化就是利用vListInitialiseItem()函数让pvContainer初始化为空。
列表项的插入删除擦操作及图示
插入
接下来就到了最难的一个部分,一个链表的每一个结点是分指针域和数值域的,但是列表和列表项它的指针都不止一个是为什么呢?是因为我们在遍历一个列表时,知道这个列表项属于哪个列表,列表是干什么的,还有如何更好的遍历一个列表,这些操作就意味着我们不可能只用一个指针。现在我们首先通过图示的方法来对这个进行一个讲解。
首先我们展示一个列表的插入函数,我们使用vListInsert()这个函数,我们使用这个函数来进行一个列表项的插入
列表的插入有两种方法,但是我们只需要记住一点我们插入的一定是pxIndex指向的列表项的前面。
其实一个列表在这里只需要使用xListEnd这个列表项,要知道一个是让pxNext指向下一个列表项,让pxPrevious指向上一个列表项,但是有些人会奇怪,为什么在这张图上会发现它的这两个指针都指向对方呢?其实不难看出,这是一个刚初始化完以后的一个列表项,他没有其他的列表项,所以当我们在按照我刚刚说的我们便可以发现这样是符合的,因为头结点的上一个就是尾结点。为此我再插入一个不是刚初始化完的列表供大家比较。
此时我们发现我们在插入的列表项都是在列表项的后面插入,但是我们如果想在列表后面插入此时就需要使用到vListInsertEnd();这个函数。在这里我给大家插入两张图看看区别
我们发现明明没有太大的改变这个函数是怎么将列表项插入到列表候得呢?这个时候我们就会发现一个非常重要的一个点xListEnd这个列表项的pxIndex没有指向本身,而pxIndex是干什么的是用来遍历的我们可以知道vListInsertEnd()是将列表项插入到pxIndex指向的前面。
删除
删除就很简单了,就使用uxListRemove()中间写上我们要删除的列表项即可。
以上就是我知道的关于列表与列表项的全部内容,可能有些地方说错的或者不对的希望大家可以及时和我说一下,我好给以后的读者一个更加准确的讲解,谢谢。
最后
以上就是兴奋秀发为你收集整理的FreeRTOS学习——列表与列表项的全部内容,希望文章能够帮你解决FreeRTOS学习——列表与列表项所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复